Commit a635454481f1b3c26cdb63361a797901eb8143f1

Authored by wugian
1 parent d7ea7ebe

fangtang 使用集成sdk使用文档

Showing 1 changed file with 553 additions and 0 deletions
  1 +# 方糖相关文档
  2 +
  3 +标签(空格分隔): work
  4 +
  5 +---
  6 +
  7 +# 1.智能模块
  8 +
  9 +## 1.1 门锁蓝牙控制模块
  10 +门锁使用的desman的方案,基于蓝牙4.0,官方app是小滴管家。通过其提供的android sdk(`greenbluetoothlelib.jar`),可以实现开关的控制。sdk中通过蓝牙模块的mac(蓝牙名以`IDLOCK_`开头) 地址区分不同的门锁.
  11 +主要使用流程概述如下
  12 +> * 注册启动相关服务
  13 +```java
  14 +//androidmanifest
  15 +<service android:name="com.bluetoothle.GREENBluetoothLeService" android:enabled="true"/>
  16 +//activity onCreate
  17 +startService(new Intent(this, GREENBluetoothLeService.class));
  18 +```
  19 +> * 发送开锁命令,其中mac地址会根据实际布置进行绑定
  20 +```java
  21 +private BLEBroadcastReceiver bleBroadcastReceiver = new BLEBroadcastReceiver();
  22 +bleBroadcastReceiver.setResponseObj(new GREENCITYBLEProtocolFactory.GREENCITYBleDataWritten() {
  23 +
  24 + @Override
  25 + public void writeSuccess() {
  26 + bleBroadcastReceiver.setResponseObj(null);
  27 + Toast.makeText(MainActivity.this, "开门成功", Toast.LENGTH_SHORT).show();
  28 +
  29 + BLEOpenRecord bleOpenRecord = new BLEOpenRecord();
  30 + bleOpenRecord.setLockmac("DC:F6:70:C1:AA:D6");
  31 + bleOpenRecord.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).format(new Date()));
  32 + Intent intent = new Intent();
  33 + intent.setAction(GREENBluetoothLeService.ACTION_OPEN_SUCCESS);
  34 + intent.putExtra("openrecord", bleOpenRecord);
  35 + sendBroadcast(intent);
  36 + }
  37 +
  38 + @Override
  39 + public void writeFailure(String error) {
  40 + bleBroadcastReceiver.setResponseObj(null);
  41 + Toast.makeText(MainActivity.this, "开门失败," + error, Toast.LENGTH_SHORT).show();
  42 + }
  43 +
  44 + });
  45 + GREENBLE.send(this, "DC:F6:70:C1:AA:D6", openCMD.getBytes());
  46 +```
  47 +
  48 +## 1.2 智能灯光
  49 +智能灯光使用的是大豆的方案,基于蓝牙4.0,官方app是dadouLight。使用时需要`add mess`,基出厂的默认配置均为`mesh name:telink_zz,pwd:123`,配置成功后,调用相关方法可以通过mesh name寻找当前范围内是否有相关智能灯存在,若存在会登录,成功后即可控制。
  50 +主要使用流程概述如下
  51 +> * 注册application主要用于初始化`Mesh`启动灯光相关服务
  52 +```java
  53 +public class FangTangApplication extends TelinkApplication {
  54 + private Mesh mesh;
  55 +
  56 + @Override
  57 + public void onCreate() {
  58 + super.onCreate();
  59 + AdvanceStrategy.setDefault(new MySampleAdvanceStrategy());
  60 + }
  61 +
  62 + @Override
  63 + public void doInit() {
  64 + super.doInit();
  65 + if (FileSystem.exists(Mesh.MESH_FILE_NAME)) {
  66 + this.mesh = (Mesh) FileSystem.readAsObject(Mesh.MESH_FILE_NAME);
  67 + }
  68 + Log.d("SMCService", "doInit");
  69 + //启动LightService
  70 + this.startLightService(TelinkLightService.class);
  71 + }
  72 + public Mesh getMesh() {
  73 + return this.mesh;
  74 + }
  75 + public void setMesh(Mesh mesh) {
  76 + this.mesh = mesh;
  77 + }
  78 + public boolean isEmptyMesh() {
  79 + return this.mesh == null;
  80 + }
  81 +}
  82 +```
  83 +> * 声名服务继承于`LightService`,启动`LightAdapter`
  84 +```java
  85 +public final class TelinkLightService extends LightService {
  86 + private static TelinkLightService mThis;
  87 + public static TelinkLightService Instance() {
  88 + return mThis;
  89 + }
  90 +
  91 + @Override
  92 + public IBinder onBind(Intent intent) {
  93 +.....
  94 + }
  95 +
  96 + @Override
  97 + public void onCreate() {
  98 + super.onCreate();
  99 + mThis = this;
  100 + if (this.mAdapter == null)
  101 + this.mAdapter = new LightAdapter();
  102 + this.mAdapter.start(this);
  103 + }
  104 +
  105 + public class LocalBinder extends Binder {
  106 + public TelinkLightService getService() {
  107 + return TelinkLightService.this;
  108 + }
  109 + }
  110 +}
  111 +```
  112 +> * 启动蓝牙
  113 +```java
  114 +if (!LeBluetooth.getInstance().isEnabled()) {
  115 + LeBluetooth.getInstance().enable(getApplicationContext());
  116 + Log.d(TAG, "开启蓝牙,体验智能灯!");
  117 +}
  118 +```
  119 +
  120 +> * 自动连接
  121 +```java
  122 +if (TelinkLightService.Instance() != null) {
  123 + Log.d(TAG, "connect not null");
  124 + if (TelinkLightService.Instance().getMode() != LightAdapter.MODE_AUTO_CONNECT_MESH) {
  125 + Lights.getInstance().clear();
  126 + if (mApplication.isEmptyMesh())
  127 + return;
  128 + Mesh mesh = mApplication.getMesh();
  129 + //自动重连参数
  130 + LeAutoConnectParameters connectParams = Parameters.createAutoConnectParameters();
  131 + connectParams.setMeshName(mesh.name);
  132 + connectParams.setPassword(mesh.password);
  133 + connectParams.autoEnableNotification(true);
  134 + //自动重连
  135 + TelinkLightService.Instance().autoConnect(connectParams);
  136 + } else {
  137 + Log.d(TAG, "connect null");
  138 + }
  139 +
  140 + //刷新Notify参数
  141 + LeRefreshNotifyParameters refreshNotifyParams = Parameters.createRefreshNotifyParameters();
  142 + refreshNotifyParams.setRefreshRepeatCount(2);
  143 + refreshNotifyParams.setRefreshInterval(2000);
  144 + //开启自动刷新Notify
  145 + TelinkLightService.Instance().autoRefreshNotify(refreshNotifyParams);
  146 + }
  147 +```
  148 +> * 监听扫描成功。其sdk基于event bus通知消息,实现接口`EventListener<String> `重写方法`public void performed(Event<String> event)`即可,其中涉及到的一些具体逻辑处理方法可参见代码
  149 +
  150 +```java
  151 + @Override
  152 +public void performed(Event<String> event) {
  153 + switch (event.getType()) {
  154 + case NotificationEvent.ONLINE_STATUS:
  155 + onOnlineStatusNotify((NotificationEvent) event);
  156 + break;
  157 + case DeviceEvent.STATUS_CHANGED:
  158 + onDeviceStatusChanged((DeviceEvent) event);
  159 + break;
  160 + case MeshEvent.OFFLINE:
  161 + onMeshOffline((MeshEvent) event);
  162 + break;
  163 + case MeshEvent.ERROR:
  164 + onMeshError((MeshEvent) event);
  165 + break;
  166 + case ServiceEvent.SERVICE_CONNECTED:
  167 + onServiceConnected((ServiceEvent) event);
  168 + break;
  169 + case ServiceEvent.SERVICE_DISCONNECTED:
  170 + onServiceDisconnected((ServiceEvent) event);
  171 + break;
  172 + }
  173 + }
  174 +```
  175 +
  176 +> * 基本控制方法,开关及亮度色温控制,其中传递不同的`address`可以控制不同的灯,`0xFFFF`表示当前mesh中所有的灯,如代码中注释了的`addr = 0x8003;`表示组为`0x8003的所有灯`。
  177 +
  178 +```java
  179 + private void open() {
  180 + byte opcode = (byte) 0xD0;
  181 + int address = 0xFFFF;
  182 + byte[] params = new byte[]{0x01, 0x00, 0x00};
  183 + if (TelinkLightService.Instance().sendCommandNoResponse(opcode, address, params)) {
  184 + Log.d("aidl","open all success");
  185 + }
  186 + }
  187 +
  188 + private void close() {
  189 + byte opcode = (byte) 0xD0;
  190 + int address = 0xFFFF;
  191 + byte[] params = new byte[]{0x00, 0x00, 0x00};
  192 + if (TelinkLightService.Instance().sendCommandNoResponse(opcode, address, params)) {
  193 + Log.d("aidl","open all success");
  194 + }
  195 + }
  196 +
  197 + private void setBrightness(int value) {
  198 + int addr = 0xFFFF;
  199 + //change group brightness or color temperature
  200 + //addr = 0x8003;
  201 + byte opcode;
  202 + byte[] params;
  203 + opcode = (byte) 0xD2;
  204 + params = new byte[]{(byte) value};
  205 + TelinkLightService.Instance().sendCommandNoResponse(opcode, addr, params, true);
  206 + }
  207 +
  208 +
  209 + private void setTemperature{
  210 + int addr = 0xFFFF;
  211 + //change group brightness or color temperature
  212 + //addr = 0x8003;
  213 + byte opcode;
  214 + byte[] params;
  215 + opcode = (byte) 0xE2;
  216 + params = new byte[]{0x05, (byte) value};
  217 + TelinkLightService.Instance().sendCommandNoResponse(opcode, addr, params, true);
  218 + }
  219 +```
  220 +
  221 +> * 对亮度色温渐变处理时需要添加额外逻辑
  222 +
  223 +## 1.3 智能开关
  224 +智能开关使用的思唯奇的方案,基于网络,现使用是通过投影控制,只使用了局域网相关功能,没有调试公网功能,其控制主机hub可连接2.4G网络,不支持5G网络。官方app为homelf,可在其官网下载http://www.adroplat.com/homelf/app/android/download/homelf.apk。
  225 +使用流程,先添加主机(hub),若是没有配置过的主机需要先联结其自带的wifi homelf才能发现主机,并设置相应控制密码(官方app是自己算出一个随机字符串设置),若是已配置过的直接在其所在2.4G wifi下添加发现即可。添加开关的步骤是,当开关面板全关时长按其中一路到所有路闪烁,后点添加按钮,成功后会有相关提示。
  226 +集成sdk相关函数介绍
  227 +```java
  228 +public class Device implements Serializable, Cloneable {
  229 + private static final long serialVersionUID = -1055014034866886590L;
  230 +
  231 + private static Device instance;
  232 +
  233 + private Device() {
  234 + }
  235 +
  236 + public static Device getInstance() {
  237 + if (null == instance) {
  238 + instance = new Device();
  239 + }
  240 + Device hub;
  241 + try {
  242 + hub = (Device) instance.clone();
  243 + } catch (CloneNotSupportedException e) {
  244 + hub = new Device();
  245 + }
  246 + return hub;
  247 + }
  248 +
  249 + /**
  250 + * 控制ID
  251 + */
  252 + private long ControllerId;
  253 + /**
  254 + * 命令类型
  255 + */
  256 + private int CmdType;
  257 + /**
  258 + * 错误码
  259 + */
  260 + private byte ErrorCode;
  261 + /**
  262 + * 设备IP
  263 + */
  264 + private byte[] DeviceIp;
  265 + /**
  266 + * 设备端口
  267 + */
  268 + private int DevicePort;
  269 + /**
  270 + * 设备公网IP
  271 + */
  272 + private byte[] MappedIp;
  273 + /**
  274 + * 设备公网端口
  275 + */
  276 + private int MappedPort;
  277 + /**
  278 + * 设备号
  279 + */
  280 + private byte[] DeviceNum;
  281 + /**
  282 + * 设备口令
  283 + */
  284 + private byte[] DeviceKey;
  285 + /**
  286 + * 是否是广域网控制
  287 + */
  288 + private boolean IsWan;
  289 + /**
  290 + * 子设备
  291 + */
  292 + private ArrayList<SubDevice> SubDevices;
  293 +
  294 + public long getControllerId() {
  295 + return ControllerId;
  296 + }
  297 +
  298 + public void setControllerId(long controllerId) {
  299 + ControllerId = controllerId;
  300 + }
  301 +
  302 + public int getCmdType() {
  303 + return CmdType;
  304 + }
  305 +
  306 + public void setCmdType(int cmdType) {
  307 + CmdType = cmdType;
  308 + }
  309 +
  310 + public byte getErrorCode() {
  311 + return ErrorCode;
  312 + }
  313 +
  314 + public void setErrorCode(byte errorCode) {
  315 + ErrorCode = errorCode;
  316 + }
  317 +
  318 + public byte[] getDeviceIp() {
  319 + return DeviceIp;
  320 + }
  321 +
  322 + public String getStringDeviceIp() {
  323 + String strIp = "null";
  324 + if (null != DeviceIp) {
  325 + char point = '.';
  326 + StringBuilder builder = new StringBuilder();
  327 + for (byte b : DeviceIp) {
  328 + builder.append((b & GlobalVar.MAX_BYTE)).append(point);
  329 + }
  330 + builder.deleteCharAt(builder.length() - 1);
  331 + strIp = builder.toString();
  332 + }
  333 + return strIp;
  334 + }
  335 +
  336 + public void setDeviceIp(byte[] deviceIp) {
  337 + DeviceIp = deviceIp;
  338 + }
  339 +
  340 + public int getDevicePort() {
  341 + return DevicePort;
  342 + }
  343 +
  344 + public void setDevicePort(int devicePort) {
  345 + DevicePort = devicePort;
  346 + }
  347 +
  348 + public byte[] getMappedIp() {
  349 + return MappedIp;
  350 + }
  351 +
  352 + public void setMappedIp(byte[] mappedIp) {
  353 + MappedIp = mappedIp;
  354 + }
  355 +
  356 + public int getMappedPort() {
  357 + return MappedPort;
  358 + }
  359 +
  360 + public void setMappedPort(int mappedPort) {
  361 + MappedPort = mappedPort;
  362 + }
  363 +
  364 + public byte[] getDeviceNum() {
  365 + return DeviceNum;
  366 + }
  367 +
  368 + //添加 转化成16进制显示 17.03.23
  369 + public String getStringDeviceNum() {
  370 + String strIp = "null";
  371 + if (null != DeviceNum) {
  372 + char point = ':';
  373 + StringBuilder builder = new StringBuilder();
  374 + for (byte b : DeviceNum) {
  375 + builder.append(decimal2hex(b & GlobalVar.MAX_BYTE)).append(point);
  376 + }
  377 + builder.deleteCharAt(builder.length() - 1);
  378 + strIp = builder.toString();
  379 + }
  380 + return strIp;
  381 + }
  382 + // precondition: d is a nonnegative integer
  383 + public static String decimal2hex(int d) {
  384 + String digits = "0123456789ABCDEF";
  385 + if (d <= 0) return "00";
  386 + int base = 16; // flexible to change in any base under 16
  387 + String hex = "";
  388 + while (d > 0) {
  389 + int digit = d % base; // rightmost digit
  390 + hex = digits.charAt(digit) + hex; // string concatenation
  391 + d = d / base;
  392 + }
  393 + return hex;
  394 + }
  395 +
  396 + public void setDeviceNum(byte[] deviceNum) {
  397 + DeviceNum = deviceNum;
  398 + }
  399 +
  400 + public byte[] getDeviceKey() {
  401 + return DeviceKey;
  402 + }
  403 +
  404 + public String getDeviceStrKey() {
  405 + String strKey = "";
  406 + try {
  407 + strKey = new String(DeviceKey, GlobalVar.CHARSET_UTF8);
  408 + } catch (UnsupportedEncodingException e) {
  409 + e.printStackTrace();
  410 + }
  411 + return strKey;
  412 + }
  413 +
  414 + public void setDeviceKey(byte[] deviceKey) {
  415 + DeviceKey = deviceKey;
  416 + }
  417 +
  418 + public boolean isWan() {
  419 + return IsWan;
  420 + }
  421 +
  422 + public void setWan(boolean wan) {
  423 + IsWan = wan;
  424 + }
  425 +
  426 + public ArrayList<SubDevice> getSubDevices() {
  427 + return SubDevices;
  428 + }
  429 +
  430 + public void setSubDevices(ArrayList<SubDevice> subDevices) {
  431 + this.SubDevices = subDevices;
  432 + }
  433 +
  434 + /**
  435 + * DeviceNum转换成long
  436 + *
  437 + * @return
  438 + */
  439 + public long getLongDeviceNum() {
  440 + return ByteUtils.macArrayToLong(DeviceNum);
  441 + }
  442 +
  443 + /**
  444 + * DeviceKey转换成long
  445 + *
  446 + * @return
  447 + */
  448 + public long getLongDeviceKey() {
  449 + return ByteUtils.macArrayToLong(DeviceKey);
  450 + }
  451 +
  452 + /**
  453 + * MappedIp转换成int
  454 + *
  455 + * @return
  456 + */
  457 + public int getIntMappedIp() {
  458 + return ByteUtils.byteArrayToInt(MappedIp);
  459 + }
  460 +
  461 + /**
  462 + * DeviceIp转换成int
  463 + *
  464 + * @return
  465 + */
  466 + public int getIntDeviceIp() {
  467 + return ByteUtils.byteArrayToInt(DeviceIp);
  468 + }
  469 +}
  470 +
  471 +public class SubDevice implements Cloneable {
  472 +
  473 + private static SubDevice instance;
  474 +
  475 + private SubDevice() {
  476 + }
  477 +
  478 + public static SubDevice getInstance() {
  479 + if (null == instance) {
  480 + instance = new SubDevice();
  481 + }
  482 + SubDevice subDevice = null;
  483 + try {
  484 + subDevice = (SubDevice) instance.clone();
  485 + } catch (CloneNotSupportedException e) {
  486 + e.printStackTrace();
  487 + }
  488 + if (null == subDevice) {
  489 + subDevice = new SubDevice();
  490 + }
  491 + return subDevice;
  492 + }
  493 +
  494 + private long SubDeviceNum;
  495 + private int SubDeviceType;
  496 + private int SubDeviceStatus;
  497 + private int SubDeviceOnlineStatus;
  498 + private int SubDeviceBit;
  499 +
  500 +
  501 + public long getSubDeviceNum() {
  502 +
  503 + return SubDeviceNum;
  504 + }
  505 +
  506 + public void setSubDeviceNum(long subDeviceNum) {
  507 +
  508 + SubDeviceNum = subDeviceNum;
  509 + }
  510 +
  511 + public int getSubDeviceType() {
  512 + return SubDeviceType;
  513 + }
  514 +
  515 + public void setSubDeviceType(int subDeviceType) {
  516 +
  517 + SubDeviceType = subDeviceType;
  518 + }
  519 +
  520 + public int getSubDeviceStatus() {
  521 + return SubDeviceStatus;
  522 + }
  523 +
  524 + public void setSubDeviceStatus(int subDeviceStatus) {
  525 +
  526 + SubDeviceStatus = subDeviceStatus;
  527 + }
  528 +
  529 + public int getSubDeviceOnlineStatus() {
  530 + return SubDeviceOnlineStatus;
  531 + }
  532 +
  533 + public void setSubDeviceOnlineStatus(int subDeviceOnlineStatus) {
  534 + SubDeviceOnlineStatus = subDeviceOnlineStatus;
  535 + }
  536 +
  537 + public int getSubDeviceBit() {
  538 + return SubDeviceBit;
  539 + }
  540 +
  541 + public void setSubDeviceBit(int subDeviceBit) {
  542 + SubDeviceBit = subDeviceBit;
  543 + }
  544 +}
  545 +
  546 +```
  547 +> * 启动sdk(调用`FistJni.getInstance().startSdk()`)后会自动调用`FistJni`中的FistListener方法.调用'FistJni.getInstance().searchLocalDevice()'可扫描当前网络中所有主机信息,若有相关信息返回,fistListerner中会执行`case FistProtocol.CommondType.CMD_TYPE_SEARCH_RESPONS`,之后可心根据需求做相应的处理。
  548 +> * `public void query(final String jsonDevice)`:jsonDevice是主机的json字符串,获取当前主机所有了子设备(开关),`FistProtocol.CommondType.CMD_TYPE_QUERY_RESPONSE`
  549 +> * `public void normalC(final String jsonDevice)`:控制开关。获取需要控制的subdevice设置相应的状态(1开,0关),将其单独添加到所属的Device中后转化成json串,调用相关方法发送指令 。`FistProtocol.CommondType.CMD_TYPE_CONTROL_DONE_RESPONSE FistProtocol.CommondType.CMD_TYPE_CONTROL_RESPONSE FistProtocol.CommondType.CMD_TYPE_CONTROL `
  550 +> * ` public void delSub(final String jsonDevice)`:删除相关开关,使用方法如上类似 `FistProtocol.CommondType.CMD_TYPE_ADD_RESPONSE`
  551 +> * `startAdd(String hubJson),stopAdd(String hubJson)`:添加删除开关,使用hub的信息。如上长按闪烁后添加,结束后调任stop,以免影响主机正常工作。
  552 +> * `modifyPwd(String hubJson,String pwd)`:设置hub的控制密码
  553 +> * `getlinkRouter(String hubJson,String ssid,String pwd)`:配置路由器信息。
Please register or login to post a comment