fangtang.md 17.4 KB

方糖相关文档

标签(空格分隔): work


1.智能模块

1.1 门锁蓝牙控制模块

门锁使用的desman的方案,基于蓝牙4.0,官方app是小滴管家。通过其提供的android sdk(greenbluetoothlelib.jar),可以实现开关的控制。sdk中通过蓝牙模块的mac(蓝牙名以IDLOCK_开头) 地址区分不同的门锁.在启动GREENBluetoothLeService时,其'onCreate'代码中有重启ble相关操作GREENBluetoothLeService.restartBleDevice(),故会导致蓝牙遥控器短暂失效。 主要使用流程概述如下

  • 注册启动相关服务 java //androidmanifest <service android:name="com.bluetoothle.GREENBluetoothLeService" android:enabled="true"/> //activity onCreate startService(new Intent(this, GREENBluetoothLeService.class));
  • 发送开锁命令,其中mac地址会根据实际布置进行绑定 ```java private BLEBroadcastReceiver bleBroadcastReceiver = new BLEBroadcastReceiver(); bleBroadcastReceiver.setResponseObj(new GREENCITYBLEProtocolFactory.GREENCITYBleDataWritten() {
        @Override
        public void writeSuccess() {
            bleBroadcastReceiver.setResponseObj(null);
            Toast.makeText(MainActivity.this, "开门成功", Toast.LENGTH_SHORT).show();

            BLEOpenRecord bleOpenRecord = new BLEOpenRecord();
            bleOpenRecord.setLockmac("DC:F6:70:C1:AA:D6");
            bleOpenRecord.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).format(new Date()));
            Intent intent = new Intent();
            intent.setAction(GREENBluetoothLeService.ACTION_OPEN_SUCCESS);
            intent.putExtra("openrecord", bleOpenRecord);
            sendBroadcast(intent);
        }

        @Override
        public void writeFailure(String error) {
            bleBroadcastReceiver.setResponseObj(null);
            Toast.makeText(MainActivity.this, "开门失败," + error, Toast.LENGTH_SHORT).show();
        }

    });
    GREENBLE.send(this, "DC:F6:70:C1:AA:D6", openCMD.getBytes());

## 1.2 智能灯光  
智能灯光使用的是大豆的方案,基于蓝牙4.0,官方app是dadouLight。使用时需要`add mess`,基出厂的默认配置均为`mesh name:telink_zz,pwd:123`,配置成功后,调用相关方法可以通过mesh name寻找当前范围内是否有相关智能灯存在,若存在会登录,成功后即可控制。踢除后灯光成功登录后灯光下显示的是3F:99,此时`mesh name `应为`out_of_mesh`   
**注意:在重设置`mesh name`时,在设置mesh页面将`mesh name` 填入`factory name`,保存后,一定要等所连灯消失后再去点`network scanning`,否则很大的可能会设置失败,失败后需要将,`mesh name `改回去再改一次**   
主要使用流程概述如下
> * 注册application主要用于初始化`Mesh`启动灯光相关服务
```java
public class FangTangApplication extends TelinkApplication {
    private Mesh mesh;

    @Override
    public void onCreate() {
        super.onCreate();
        AdvanceStrategy.setDefault(new MySampleAdvanceStrategy());
    }

    @Override
    public void doInit() {
        super.doInit();
        if (FileSystem.exists(Mesh.MESH_FILE_NAME)) {
            this.mesh = (Mesh) FileSystem.readAsObject(Mesh.MESH_FILE_NAME);
        }
        Log.d("SMCService", "doInit");
        //启动LightService
        this.startLightService(TelinkLightService.class);
    }
    public Mesh getMesh() {
        return this.mesh;
    }
    public void setMesh(Mesh mesh) {
        this.mesh = mesh;
    }
    public boolean isEmptyMesh() {
        return this.mesh == null;
    }
}
  • 声名服务继承于LightService,启动LightAdapter ```java public final class TelinkLightService extends LightService { private static TelinkLightService mThis; public static TelinkLightService Instance() { return mThis; }
@Override
public IBinder onBind(Intent intent) {

..... }

@Override
public void onCreate() {
    super.onCreate();
    mThis = this;
    if (this.mAdapter == null)
        this.mAdapter = new LightAdapter();
    this.mAdapter.start(this);
}

public class LocalBinder extends Binder {
    public TelinkLightService getService() {
        return TelinkLightService.this;
    }
}

}

> * 启动蓝牙
```java
if (!LeBluetooth.getInstance().isEnabled()) {
    LeBluetooth.getInstance().enable(getApplicationContext());
    Log.d(TAG, "开启蓝牙,体验智能灯!");
}
  • 自动连接
    ```java if (TelinkLightService.Instance() != null) { Log.d(TAG, "connect not null"); if (TelinkLightService.Instance().getMode() != LightAdapter.MODE_AUTO_CONNECT_MESH) { Lights.getInstance().clear(); if (mApplication.isEmptyMesh()) return; Mesh mesh = mApplication.getMesh(); //自动重连参数 LeAutoConnectParameters connectParams = Parameters.createAutoConnectParameters(); connectParams.setMeshName(mesh.name); connectParams.setPassword(mesh.password); connectParams.autoEnableNotification(true); //自动重连 TelinkLightService.Instance().autoConnect(connectParams); } else { Log.d(TAG, "connect null"); }
        //刷新Notify参数
        LeRefreshNotifyParameters refreshNotifyParams = Parameters.createRefreshNotifyParameters();
        refreshNotifyParams.setRefreshRepeatCount(2);
        refreshNotifyParams.setRefreshInterval(2000);
        //开启自动刷新Notify
        TelinkLightService.Instance().autoRefreshNotify(refreshNotifyParams);
    }
> * 监听扫描成功。其sdk基于event bus通知消息,实现接口`EventListener<String> `重写方法`public void performed(Event<String> event)`即可,其中涉及到的一些具体逻辑处理方法可参见代码  

```java
 @Override
public void performed(Event<String> event) {
        switch (event.getType()) {
            case NotificationEvent.ONLINE_STATUS:
                onOnlineStatusNotify((NotificationEvent) event);
                break;
            case DeviceEvent.STATUS_CHANGED:
                onDeviceStatusChanged((DeviceEvent) event);
                break;
            case MeshEvent.OFFLINE:
                onMeshOffline((MeshEvent) event);
                break;
            case MeshEvent.ERROR:
                onMeshError((MeshEvent) event);
                break;
            case ServiceEvent.SERVICE_CONNECTED:
                onServiceConnected((ServiceEvent) event);
                break;
            case ServiceEvent.SERVICE_DISCONNECTED:
                onServiceDisconnected((ServiceEvent) event);
                break;
        }
    }
  • 基本控制方法,开关及亮度色温控制,其中传递不同的address可以控制不同的灯,0xFFFF表示当前mesh中所有的灯,如代码中注释了的addr = 0x8003;表示组为0x8003的所有灯
    private void open() {
        byte opcode = (byte) 0xD0;
        int address = 0xFFFF;
        byte[] params = new byte[]{0x01, 0x00, 0x00};
        if (TelinkLightService.Instance().sendCommandNoResponse(opcode, address, params)) {
            Log.d("aidl","open all success");
        }
    }

    private void close() {
        byte opcode = (byte) 0xD0;
        int address = 0xFFFF;
        byte[] params = new byte[]{0x00, 0x00, 0x00};
        if (TelinkLightService.Instance().sendCommandNoResponse(opcode, address, params)) {
            Log.d("aidl","open all success");
        }
    }

     private void setBrightness(int value) {
        int addr = 0xFFFF;
        //change group brightness or color temperature
        //addr = 0x8003;
        byte opcode;
        byte[] params;
        opcode = (byte) 0xD2;
        params = new byte[]{(byte) value};
        TelinkLightService.Instance().sendCommandNoResponse(opcode, addr, params, true);
    }


     private void setTemperature{
        int addr = 0xFFFF;
        //change group brightness or color temperature
        //addr = 0x8003;
        byte opcode;
        byte[] params;
        opcode = (byte) 0xE2;
        params = new byte[]{0x05, (byte) value};
        TelinkLightService.Instance().sendCommandNoResponse(opcode, addr, params, true);
    }
  • 对亮度色温渐变处理时需要添加额外逻辑

1.3 智能开关

智能开关使用的思唯奇的方案,基于网络,现使用是通过投影控制,只使用了局域网相关功能,没有调试公网功能,其控制主机hub可连接2.4G网络,不支持5G网络。官方app为homelf,可在其官网下载http://www.adroplat.com/homelf/app/android/download/homelf.apk。 使用流程,先添加主机(hub),若是没有配置过的主机需要先联结其自带的wifi homelf才能发现主机,并设置相应控制密码(官方app是自己算出一个随机字符串设置),若是已配置过的直接在其所在2.4G wifi下添加发现即可。添加开关的步骤是,当开关面板全关时长按其中一路到所有路闪烁,后点添加按钮,成功后会有相关提示。 集成sdk相关函数介绍

public class Device implements Serializable, Cloneable {
    private static final long serialVersionUID = -1055014034866886590L;

    private static Device instance;

    private Device() {
    }

    public static Device getInstance() {
        if (null == instance) {
            instance = new Device();
        }
        Device hub;
        try {
            hub = (Device) instance.clone();
        } catch (CloneNotSupportedException e) {
            hub = new Device();
        }
        return hub;
    }

    /**
     * 控制ID
     */
    private long ControllerId;
    /**
     * 命令类型
     */
    private int CmdType;
    /**
     * 错误码
     */
    private byte ErrorCode;
    /**
     * 设备IP
     */
    private byte[] DeviceIp;
    /**
     * 设备端口
     */
    private int DevicePort;
    /**
     * 设备公网IP
     */
    private byte[] MappedIp;
    /**
     * 设备公网端口
     */
    private int MappedPort;
    /**
     * 设备号
     */
    private byte[] DeviceNum;
    /**
     * 设备口令
     */
    private byte[] DeviceKey;
    /**
     * 是否是广域网控制
     */
    private boolean IsWan;
    /**
     * 子设备
     */
    private ArrayList<SubDevice> SubDevices;

    public long getControllerId() {
        return ControllerId;
    }

    public void setControllerId(long controllerId) {
        ControllerId = controllerId;
    }

    public int getCmdType() {
        return CmdType;
    }

    public void setCmdType(int cmdType) {
        CmdType = cmdType;
    }

    public byte getErrorCode() {
        return ErrorCode;
    }

    public void setErrorCode(byte errorCode) {
        ErrorCode = errorCode;
    }

    public byte[] getDeviceIp() {
        return DeviceIp;
    }

    public String getStringDeviceIp() {
        String strIp = "null";
        if (null != DeviceIp) {
            char point = '.';
            StringBuilder builder = new StringBuilder();
            for (byte b : DeviceIp) {
                builder.append((b & GlobalVar.MAX_BYTE)).append(point);
            }
            builder.deleteCharAt(builder.length() - 1);
            strIp = builder.toString();
        }
        return strIp;
    }

    public void setDeviceIp(byte[] deviceIp) {
        DeviceIp = deviceIp;
    }

    public int getDevicePort() {
        return DevicePort;
    }

    public void setDevicePort(int devicePort) {
        DevicePort = devicePort;
    }

    public byte[] getMappedIp() {
        return MappedIp;
    }

    public void setMappedIp(byte[] mappedIp) {
        MappedIp = mappedIp;
    }

    public int getMappedPort() {
        return MappedPort;
    }

    public void setMappedPort(int mappedPort) {
        MappedPort = mappedPort;
    }

    public byte[] getDeviceNum() {
        return DeviceNum;
    }

    //添加 转化成16进制显示 17.03.23
    public String getStringDeviceNum() {
        String strIp = "null";
        if (null != DeviceNum) {
            char point = ':';
            StringBuilder builder = new StringBuilder();
            for (byte b : DeviceNum) {
                builder.append(decimal2hex(b & GlobalVar.MAX_BYTE)).append(point);
            }
            builder.deleteCharAt(builder.length() - 1);
            strIp = builder.toString();
        }
        return strIp;
    }
    // precondition:  d is a nonnegative integer
    public static String decimal2hex(int d) {
        String digits = "0123456789ABCDEF";
        if (d <= 0) return "00";
        int base = 16;   // flexible to change in any base under 16
        String hex = "";
        while (d > 0) {
            int digit = d % base;              // rightmost digit
            hex = digits.charAt(digit) + hex;  // string concatenation
            d = d / base;
        }
        return hex;
    }

    public void setDeviceNum(byte[] deviceNum) {
        DeviceNum = deviceNum;
    }

    public byte[] getDeviceKey() {
        return DeviceKey;
    }

    public String getDeviceStrKey() {
        String strKey = "";
        try {
            strKey = new String(DeviceKey, GlobalVar.CHARSET_UTF8);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return strKey;
    }

    public void setDeviceKey(byte[] deviceKey) {
        DeviceKey = deviceKey;
    }

    public boolean isWan() {
        return IsWan;
    }

    public void setWan(boolean wan) {
        IsWan = wan;
    }

    public ArrayList<SubDevice> getSubDevices() {
        return SubDevices;
    }

    public void setSubDevices(ArrayList<SubDevice> subDevices) {
        this.SubDevices = subDevices;
    }

    /**
     * DeviceNum转换成long
     *
     * @return
     */
    public long getLongDeviceNum() {
        return ByteUtils.macArrayToLong(DeviceNum);
    }

    /**
     * DeviceKey转换成long
     *
     * @return
     */
    public long getLongDeviceKey() {
        return ByteUtils.macArrayToLong(DeviceKey);
    }

    /**
     * MappedIp转换成int
     *
     * @return
     */
    public int getIntMappedIp() {
        return ByteUtils.byteArrayToInt(MappedIp);
    }

    /**
     * DeviceIp转换成int
     *
     * @return
     */
    public int getIntDeviceIp() {
        return ByteUtils.byteArrayToInt(DeviceIp);
    }
}

public class SubDevice implements Cloneable {

    private static SubDevice instance;

    private SubDevice() {
    }

    public static SubDevice getInstance() {
        if (null == instance) {
            instance = new SubDevice();
        }
        SubDevice subDevice = null;
        try {
            subDevice = (SubDevice) instance.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        if (null == subDevice) {
            subDevice = new SubDevice();
        }
        return subDevice;
    }

    private long SubDeviceNum;
    private int SubDeviceType;
    private int SubDeviceStatus;
    private int SubDeviceOnlineStatus;
    private int SubDeviceBit;


    public long getSubDeviceNum() {

        return SubDeviceNum;
    }

    public void setSubDeviceNum(long subDeviceNum) {

        SubDeviceNum = subDeviceNum;
    }

    public int getSubDeviceType() {
        return SubDeviceType;
    }

    public void setSubDeviceType(int subDeviceType) {

        SubDeviceType = subDeviceType;
    }

    public int getSubDeviceStatus() {
        return SubDeviceStatus;
    }

    public void setSubDeviceStatus(int subDeviceStatus) {

        SubDeviceStatus = subDeviceStatus;
    }

    public int getSubDeviceOnlineStatus() {
        return SubDeviceOnlineStatus;
    }

    public void setSubDeviceOnlineStatus(int subDeviceOnlineStatus) {
        SubDeviceOnlineStatus = subDeviceOnlineStatus;
    }

    public int getSubDeviceBit() {
        return SubDeviceBit;
    }

    public void setSubDeviceBit(int subDeviceBit) {
        SubDeviceBit = subDeviceBit;
    }
}
  • 启动sdk(调用FistJni.getInstance().startSdk())后会自动调用FistJni中的FistListener方法.调用'FistJni.getInstance().searchLocalDevice()'可扫描当前网络中所有主机信息,若有相关信息返回,fistListerner中会执行case FistProtocol.CommondType.CMD_TYPE_SEARCH_RESPONS,之后可心根据需求做相应的处理。
  • public void query(final String jsonDevice):jsonDevice是主机的json字符串,获取当前主机所有了子设备(开关),FistProtocol.CommondType.CMD_TYPE_QUERY_RESPONSE
  • 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
  • public void delSub(final String jsonDevice):删除相关开关,使用方法如上类似 FistProtocol.CommondType.CMD_TYPE_ADD_RESPONSE
  • startAdd(String hubJson),stopAdd(String hubJson):添加删除开关,使用hub的信息。如上长按闪烁后添加,结束后调任stop,以免影响主机正常工作。
  • modifyPwd(String hubJson,String pwd):设置hub的控制密码
  • getlinkRouter(String hubJson,String ssid,String pwd):配置路由器信息。