nkaminski / csrmesh

Reverse engineered bridge implementation of the CSRMesh BTLE protocol
GNU Lesser General Public License v3.0
70 stars 20 forks source link

Incorrect Command Payload For N Bulbs In A Single Network. #11

Closed ghost closed 7 years ago

ghost commented 7 years ago

Problem: The command string built to is incorrect for a single network, one Pin, with more than one bulb.

Fix: When there is more that one bulb in a network the Application will identify each bulb in the App as "Light Bulb 1", "Light Bulb 2", etc.

The light_set_cmd generated byte string must include a byte which identifies the bulb 0x01, 0x02 etc followed by a delim byte 0x80, after the command bytes 0x73, 0x11 and before level red, green, blue bytes.

The current "def light_set_cmd(level, red, green, blue):" Given: light_set_cmd (200, 255, 255, 255) Creates: "000073110000e4ffffff"

Modify the method to take the bulb number for the network: def light_set_cmd(bulb_no, level, red, green, blue):" Given: light_set_cmd (1, 200, 255, 255, 255) Creates: "000073110180e4ffffff"

The packet may be directly sent to the target bulbs address.

The following Haskell routine builds a correct light_set_cmd byte string.

bulbCmd :: Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> ByteString
bulbCmd bulb level red green blue =
  let bld = do
        P.putWord16le 0x0000
        P.putByteString cmd
        --P.putWord16le 0x0000  -- 0x0000 for a single bulb network
        P.putWord8 bulb -- Bulb #1 0x01, #2 0x02, etc.
        P.putWord8 0x80
        P.putInt8 lvl
        P.putWord8 red
        P.putWord8 green
        P.putWord8 blue
  in P.runPut bld
  where
    cmd = BS.pack [0x73, 0x11]
    lvl :: Int8
    lvl = let l  = fromIntegral level :: Int
              l' = (l `div` 2)  - 128
          in fromIntegral l' :: Int8
nkaminski commented 7 years ago

Thanks for the suggestion, will test and integrate.

nkaminski commented 7 years ago

Made a little more progress with the reverse engineering of the proto as well. Setting a value of 0x00 after the bulb/object ID will cause the ID to be interpreted by the network as a group ID, with group 0 being reserved as the broadcast group. Setting the value to 0x80 (10000000_2) as you are in your Haskell implementation causes the ID to be interpreted as an individual device/bulb ID.