nkaminski / csrmesh

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

Unable to connect to MOVE #25

Open beanian opened 6 years ago

beanian commented 6 years ago

When I execute hcitool lescan I can see the MOVE2 which i'm assuming is my MOVE device. (I have noticed it is not CSRMESH like others have seen) image

Executing the cli results in the following error: image

Any ideas?

nkaminski commented 5 years ago

As a side note, I've been aiming to be a better open source citizen by staying on top of these issues a little more as well going forwards.

On October 24, 2018 8:35:09 AM CDT, Swiftnesses notifications@github.com wrote:

Thanks for looking into this :)

I'll need to check, I thought it needed 4 digits, let me check once I'm home, unless @andrasj can confirm first!

-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/nkaminski/csrmesh/issues/25#issuecomment-432658183

-- Sent from my Android device with K-9 Mail.

Swiftnesses commented 5 years ago

Well, if we can get this working and I can finally integrate the 8 MOVE units I have (which are useless right now!), I'll be forever grateful!

Fingers crossed we can get this working :)

andrasj commented 5 years ago

Yes, afaik my devices are running the new firmware, but I kept the short pin because I knew the old python only supported 4 digits (I didn't knew if it would be compatible, but it was a 'best shot') The new app allows network keys from 1 to 20 charachters (also alphanumeric outside the A..F hex-range). I didn't verify if I could actually add devices to these networks, but the app allowed to define them. Maybe the 'entered key' is now hashed to generate the actual 'network pin'.

@Swiftnesses : same here, all devices lying in the box, and probably will stay there, the solar panel won't be usable to continuously power the device and mains is too far away... (they now sell at 111euro per device, maybe I should sell them 2nd hand. Would be a good investment 🤑)

nkaminski commented 5 years ago

My current interpretation of the key derivation function is K(aes) = first_16_bytes(sha256(strcat(pin,"MCP\0")))

This in theory would be compatible with an arbitrary PIN size, therefore I will opt to not limit PIN size artifically in my revised implementation.

Nash

On October 24, 2018 12:40:48 PM CDT, andrasj notifications@github.com wrote:

Yes, afaik my devices are runnen the new firmware, but I kept the short pin because I knew the old python only supported 4 digits (I didn't knew if it would be compatible, but it was a 'best shot')> The new app allows network keys from 1 to 20 charachters (also alphanumeric outside the A..F hex-range). I didn't verify if I could actually add devices to these networks, but the app allowed to define them.> Maybe the 'entered key' is now hashed to generate the actual 'network pin'.>

@Swiftnesses : same here, all devices lying in the box, and probably will stay there, the solar panel won't be usable to continuously power the device and mains is too far away... (they now sell at 111euro per device, maybe I should sell them 2nd hand. Would be a good investment 🤑)

-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/nkaminski/csrmesh/issues/25#issuecomment-432758237

-- Sent from my Android device with K-9 Mail.

nkaminski commented 5 years ago

move-experimental branch now contains the code for processing and simulating PCAPs on my simple device simulator, https://github.com/nkaminski/csrmesh/commit/de26210b1184b39b1f7104d23124fbaddf8f6ce5

nkaminski commented 5 years ago

@andrasj 's capture is sent to and from the 'old' BTLE handles of 0x1e and 0x21and contains: [b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0180732200e1e100c6', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'01807322ffe1e100c7', b'0000734564b40004ff', b'01807322ffe1e100c7', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0000734564b40004ff', b'0280732200ffff00c8', b'02807322ffffff00c9']

nkaminski commented 5 years ago

So far the format is looking like: (int8 address) (uint8 flags) (constant 0x73) (uint8 opcode) (uint32 command) (uint8 sequence)

Where the first command byte corresponds to the position. Are there any other parameters that are set by the app that you think may explain the other 3 command bytes?

andrasj commented 5 years ago

I remember that in the original 'protocol description' (pdf used to be on the teptron-website) the 'SetPosition'-opcode (0x22) had 2 bytes as arguments (position & speed). But I saw that in the csrmesh implementation only the position byte was added. (and this worked with the initial firmware). So I guess the command bytes for 'SetPosition'-opcode are now: (destinationPostion, movingSpeedDirection1, movingSpeedOtherDirection), and probably 1 byte padding? I'll see if I can take another capture with 'modified' values to confirm. And if I can get the packet decoding to work. About the encryption: Is it correct to say that nothing changed between the old/new protocol? only different size of pins are allowed?

nkaminski commented 5 years ago

No encryption related changes that I have seen.

Also I'm thinking of implementing a raw mode to allow fully arbitrary data to be sent as an encrypted frame to a device. This should make testing these protocol format hypotheses much faster and easier

andrasj commented 5 years ago

something moved over here :-). But I don't get it any more... I'll try to explain. Since I'm not a python-guru, I kind of ported the code to C# in order to be able to experiment. (because of the unstable communication in the initial version). I created some equivalent of the initial csrmesh, with encryption/packet construction in C#, but I remote-executed gatttool on linux to transmit the encrypted packet. (this was with old firmware). Because I wanted to try/help out on the new firmware, I picked up the code and ported the transmission of BLE-packets to C# and windows10-UWP-api. (my previous linux-ble-devices are not available at the moment), I initially did struggle to find the correct writable characteristic, but apparently succeeded, because I could set the postion of the device. To summarize the results of my test with C#:

I need to investigate some more logs I guess. Is the split in chunks of 20 some ble/gatt-specification? I saw some special handling in your python code, but don't see where it comes from.

nkaminski commented 5 years ago

The 20 byte split and the and the "convention" of delivering the remaining data to handle+3 is strictly a csrmesh protocol semantic, it is not defined by any type of standard.

On November 1, 2018 6:45:26 PM CDT, andrasj notifications@github.com wrote:

something moved over here :-). But I don't get it any more... I'll try to explain. Since I'm not a python-guru, I kind of ported the code to C# in order to be able to experiment. (because of the unstable communication in the initial version). I created some equivalent of the initial csrmesh, with encryption/packet construction in C#, but I remote-executed gatttool on linux to transmit the encrypted packet. (this was with old firmware). Because I wanted to try/help out on the new firmware, I picked up the code and ported the transmission of BLE-packets to C# and windows10-UWP-api. (my previous linux-ble-devices are not available at the moment), I initially did struggle to find the correct writable characteristic, but apparently succeeded, because I could set the postion of the device. To summarize the results of my test with C#:

  • writing the old command structure to handle 0x20 on my device works. (maybe difference in api between gatttool & uwp?)
  • the new command structure results in encrypted packets > 20 bytes, don't work (yet).

I need to investigate some more logs I guess. Is the split in chunks of 20 some ble/gatt-specification? I saw some special handling in your python code, but don't see where it comes from.

-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/nkaminski/csrmesh/issues/25#issuecomment-435224060

-- Sent from my Android device with K-9 Mail.

nkaminski commented 5 years ago

Also, I have just pushed an experimental reimplementation of the movecontroller module to the move-experimental branch which implements the current hypothesis with regards to the new format.

Would someone be able to test this against a move running the new firmware?

andrasj commented 5 years ago

I spinned up an edison board, and tried. I did encounter an error in crypto.py line 11. I guess 'pinsize' should be 'intpinsize'. After this modification I retried: # bin/csrmesh-cli --pin 1234 --dest C1:61:18:3A:02:C1 --objid 1 --position 150 move [+] Connecting to device C1:61:18:3A:02:C1 [+] Writing 0x0f8c2600809f445ba898a35a2bfec6e18132ec97 to BTLE handle 0x1C [-] A communication error has occured: Error from Bluetooth stack (comerr) [+] BTLE disconnected [+] Communication complete [-] Operation failed how sure are we about the handle? These are the handles and capabilities for services/characteristics I discovered on my device: (uuid / handle / capabilities) svc: 00001801-0000-1000-8000-00805f9b34fb / 0x1 charac: 00002a05-0000-1000-8000-00805f9b34fb / 0x2 / Indicate

svc: 00001800-0000-1000-8000-00805f9b34fb / 0x5 charac: 00002a00-0000-1000-8000-00805f9b34fb / 0x6 / Read, Write charac: 00002a01-0000-1000-8000-00805f9b34fb / 0x8 / Read charac: 00002a04-0000-1000-8000-00805f9b34fb / 0xA / Read

svc: 00001016-d102-11e1-9b23-00025b00a5a5 / 0xC charac: 00001013-d102-11e1-9b23-00025b00a5a5 / 0xD / Read, Write charac: 00001018-d102-11e1-9b23-00025b00a5a5 / 0xF / Write charac: 00001014-d102-11e1-9b23-00025b00a5a5 / 0x11 / Read, Notify charac: 00001011-d102-11e1-9b23-00025b00a5a5 / 0x14 / Read

svc: 0000fef1-0000-1000-8000-00805f9b34fb / 0x16 charac: c4edc000-9daf-11e3-8000-00025b000b00 / 0x17 / Write charac: c4edc000-9daf-11e3-8001-00025b000b00 / 0x19 / Read charac: c4edc000-9daf-11e3-8002-00025b000b00 / 0x1B / Read, Write charac: c4edc000-9daf-11e3-8003-00025b000b00 / 0x1D / WriteWithoutResponse, Write, Notify charac: c4edc000-9daf-11e3-8004-00025b000b00 / 0x20 / WriteWithoutResponse, Write, Notify charac: c4edc000-9daf-11e3-8005-00025b000b00 / 0x23 / Read, Write charac: c4edc000-9daf-11e3-8006-00025b000b00 / 0x25 / Read, Write

Swiftnesses commented 5 years ago

I need to try this, has anyone has any luck yet?

andrasj commented 5 years ago

Hello guy's an update: I could make the device open/close the same way with python code from @nkaminski and my C# code My experience: from python I need to gattWrite on handle 0x21, in C#/UWP I need to do a write-call to the characteristic with handle 0x20. When writing: 0x01807322FF00 => device goes to position FF at default speed (open/close speed configured by app) 0x01807322FF => device goes to position FF at full speed (always full speed, this is the command I used in previous firmware) changing the last byte in the first command seems to affect the speed going from 00=>FF, but doesn't changes the speed while going from FF=>00. adding 1 byte extra results in an encrypted packet exceeding the 20-byte csrmesh limit... I guess we need to figure out how to write these extra bytes.

So to make it work: -Write to handle 0x21 -keep encrypted packet size below 20 Can anyone else confirm this?

Swiftnesses commented 5 years ago

@andrasj

Nice info, thanks!

I need to wait to find time to load up a pi zero and give it a test drive. Do you know if the mesh has improved, I used to have problems with Move devices at the extreme parameters of the house (the mesh was rubbish with the old firmware!).

I'm not experienced with Python, could you give some example commands so I can try them?

Swiftnesses commented 5 years ago

Hi @andrasj ,

Could you summarize the changes you made to get this to work - trying but having no luck :(

UPDATE:

I updated the file movecontroller.py file and changed handler to '0x0021', I now get:

pi@raspberrypi:~/move blinds/csrmesh $ ./bin/csrmesh-cli move --pin 1234 --dest FB:6B:78:7A:05:39 --objid 1 --position 255
[+] Connecting to device FB:6B:78:7A:05:39
[+] Writing 0x3d6f5c0080732dcca574f6f9c65cf5f8b72c6914 to BTLE handle 0x21
[+] Writing 0x3803ff to BTLE handle 0x24
[+] BTLE disconnected
[+] Communication complete
[+] Operation succeeded

Sadly nothing happens. I'm close to putting these things in the trash :(

andrasj commented 5 years ago

The problem is your encrypted data-packet is still bigger than 20 bytes (which didn't work yet on my devices neither). I 'shrinked' the packet by changing movecontroller.py: in the struct.pack-call remove the 'HxB' at the end and close the argument list after position. This is the equivalent of the command in the previous firmware, but it still seems to work. (at least seeing it moving will give some hope :-)) Currently, I'm trying to capture my own BLE-traffic to compare it with the official app. What I already noticed in my previous capture: -the official app also sends 0x01807316 and 0x02807316 to handle 0x21 (which according to the protocol-doc corresponds to the 'GetPosition' of device 1 and 2, so this makes sence, I had 2 devices configured in the android-app) -when the 'MoveToPosition' (0x01807322ffe1e100c7) command is sent, the first 20 bytes seem to be written to 0x1e and the remaing bytes on 0x21. But I couldn't succesfully replay that exact command.

To summarize my changes: -in crypto.py: change the issue of pinsize to intPinsize -in movecontroller.py: change handle 0x001c to 0x0021 -in movecontroller.py: change packet creation to: p_cmd = struct.pack("<BBBBB", objid, flags, magic, cmd, position)

Swiftnesses commented 5 years ago

@andrasj you're a star - we have life!

That's a fantastic start, I made a quick NODE express server so I fire up an api to talk to the Pi and issue commands from my home automation system. If we could figure out the final parameters and tidy things up, it would be amazing!

Thanks again for everyone who has put time and effort into this - much appreciated!

nkaminski commented 5 years ago

Regarding the issue of the correct handles to write to, it appears that in the series of captures in this issue the following handles are written:

@andrasj 0x1e, 0x21 @beanian 0x1c, 0x1f @Maatss 0x1c, 0x1f

This supports the observation of @andrasj seeing actions when writing to 0x21. Furthermore, this presents 2 unknowns where if understood, would be very beneficial in making this complete/stable.

andrasj commented 5 years ago

@Swiftnesses : I still think @nkaminski is the star, he provided the real magic, I'm only performing some trial/error/compare because I do have some devices (and I'ld love to learn some more about bt/ble, meanwhile helping others)

@nkaminski

andrasj commented 5 years ago

Attached you can find the output of bluetoothctl. (I did need to add commands 'menu gatt' and 'back' in order to call list-attributes.) bluetoothctl.txt

Swiftnesses commented 5 years ago

I seem to be having some issues controlling multiple devices.

Currently I'm sending ID:0 to the MAC address of the MOVE closest to the Pi. I was under the impression this should broadcast to all devices in the mesh? Sadly it seems to only work 25% of the time - most of the time only one device responds.

Making a group in the app seems to work 100% of the time, so are they sending different commands? I assume so, as the app allows for custom groups, so there must be a command for this.

@andrasj are you experiencing this issue, do you have any idea how groups are implemented?

andrasj commented 5 years ago

afaik, there is only a 'virtual' MAC address for the complete mesh. (which is maybe handed over by some kind of election when a device goes down?, or maybe the mesh is kind of static like in zigbee networks?) I have not idea how the mesh is implemented, but I guess each device does a retransmit of each received packet (if it was not in the list of the last x packets and some kind of ttl >0). These are just guesses, as long as the protocol is not stable, there is no use in knowing how/if the mesh is implemened. About the groups, I think the 'flags' byte should be zero, and the objectId would be interpreted as groupId. Remember I didn't verify this in any way, just an asumption.

About connectivity: I only used the devices with the old firmware, and the problem of 'packet loss' was one of the reasons I've sent them back to their box. Because of the new firmware, I wanted to give it one more try. (but probably won't use the devices for other reasons). I can see multiple reasons for the packet loss:

Taking BLE-captures is currently a PITA on my android device. (toggling settings, rebooting, file transfers, unzipping, decrypting, and meanwhile trying to remember what actions were done in the app while taking the capture). I would like to have an easier way to analyse the traffic of the official app, but since my device isn't rooted I didn't find an easy way (any hint are welcome). I considered buying a BT-sniffer dongle, but probably I'll only use it for this purpose, so I've not decided yet. (maybe I'll look into using another spare android device). If creating pcaps on android is going more easily I can try to look how groups are implemented. (But spare time is limited)

Swiftnesses commented 5 years ago

Hi @andrasj thanks for the reply.

I'll try the group idea you had, as groups work perfect in the app, can you point me in the direction of how I can try this perhaps?

Yes, sadly, even with the new firmware communication is still unreliable for me (in fact I don't see much of an improvement over the old firmware). The app seems to work reasonably well though, but I'm not having much look using the Pi and CSRMesh, which is a shame.

nkaminski commented 5 years ago

CSRmesh is a "dumb" flood mesh; no intelligent routing decisions are made. Therefore, I believe that the key to the unreliability is in identifying what those last several bytes represent.

In the context of a flood mesh, the sequence number (or other per-packet unique value) is essential in order to prevent packets from circulating endlessly.

Therefore, I'm considering adding a feature to allow fully arbitrary data payloads to be encrypted, packetized, and sent to a CSRMesh device so that we can easily make one byte (or smaller) changes to a replay of a packet sent by the official app.

Swiftnesses commented 5 years ago

That would be amazing... While the MOVE app isn't perfect, it does work, I'd also love to be able to retrieve data from the devices - like the app does for position and light / battery levels.

I don't have any Android devices (with exceptions of the Kid's Fire Kindles!), so am pretty useless when it comes to capturing data sadly. I can however help with testing, which I understand is of limited value at this stage...

Appreciate the work you guys are doing, I still believe the devices have value, if only we can access them effectively.

Swiftnesses commented 5 years ago

I see to have it working okay if I send each command unit by unit (using each units specific mac and ID), rather than using ID0 to one of the units (broadcast). I assume this is because it guarantees the unit is awake before it proceeds...

nkaminski commented 5 years ago

This may also explain why the official app continuously sends a string of what appear to be no-op messages. I have not worked with battery powered CSRMesh devices before, however possibly we need a preamble of  no-op/heartbeat messages sent at some rate for some minimum period of time to ensure that the entire mesh is awake prior to sending the actual command.

Powering any RF receiver circuity consumes a nontrivial amount of power and in a battery operated device, it would make sense that a device would not "listen" continuously at all times (think of a battery operated zwave node).

Nash

On 11/14/18 7:46 AM, Swiftnesses wrote:

I see to have it working okay if I send each command unit by unit (using each units specific mac and ID), rather than using ID0 to one of the units (broadcast). I assume this is because it guarantees the unit is awake before it proceeds...

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/nkaminski/csrmesh/issues/25#issuecomment-438666940, or mute the thread https://github.com/notifications/unsubscribe-auth/ACXl4eae8vEM8WJvrhj4USHz-VSZizF9ks5uvB7KgaJpZM4R-TPg.

heggink commented 5 years ago

Hi everyone, just stumbled upon this thread trying to get my new 2 moves to work with domoticz. ANy update on this and a new version of csrmesh?

andrasj commented 5 years ago

@heggink : I think the master branch should work (on both new/old firmware), but will only support 'goToPosition'. (for teptron move) However:

@Swiftnesses : how did you get the specific mac-address? my devices always seem to join the network of the first booted device (which generates a random mac).

While re-reading this thread, I also see that some people have their device advertising as 'MOVE2' mine still advertises as 'MOVE'.

I think we have currently quite some information which isn't consistent all the time. maybe we should first make a summary of what is currently known about the different versions of the 'move' devices (how advertised/which handles used/which software and commands are working/...). Then we can think how to fill in the 'unknown'.

FYI: I meanwhile bought a simple BLE-sniffer ( https://www.adafruit.com/product/2269 ), and noticed that when the android app says 'waking all devices' (when trying to add a new device), it looks like there is some address-spoofing going on (suddenly lot's of new mac-addresses are detected).

Swiftnesses commented 5 years ago

@andrasj To be honest, I just figured out which mac was which device, I then sent a command with the right ID and MAC, which seems to work 100% of the time. Quite frankly though it sucks, as once a device is rebooted, it changes MAC address, so I need to rebuild my flows.

I didn't have much luck with the broadcast ID, it was too hit and miss.

Expected we could make more of these, but I'm pretty much ready to accept defeat.

andrasj commented 5 years ago

I only changed objectId, and it seemed to work most of the time. after a second look, I indeed have a 2nd mac when powering up an additional device. But if sending to the correct mac is reliable, this could be a workaround for people who don't need the mesh functionality. (potentially broadcasting to all advertising 'MOVE' mac's)

Additionally, I just did some additional test to receive notifications of value-changes, and maybe this could also be used as a check if the devices is responding or needs resend. When sending 'gotoposition 255', the move immediately raises a value-changed-event with data: charac 0x20 Value (19 bytes): 0x16E2A2018009C61529AF9BE8EF47035CB18B32 and when the device stops moving, it raises another value-changed, but this time with bigger data (also over 2 handles): charac 0x1D Value (20 bytes): 0x17E2A201804607047D79FC272D874B891F19CF28 charac 0x20 Value (6 bytes): 0xBC040C066F32

the first byte seems to be a sequence number and increments for each 'value-changed', the next bytes E2A20180 seem to be static in my first couple of tests.

maybe @nkaminski has some more knowledge about the notification events, Is the data also encrypted? (probably it is), Same decryption routines? (currently I cannot make any sense of it). maybe the 3rd byte is a response code, because the old pdf says 0xA2 is the success response of the move to position command. (should check some other commands)

Swiftnesses commented 5 years ago

Hi Guys,

Just checking in to see how progress is on this? I've given up again as my units needs rebooting now and again which means the MAC changes (hence my script then fails)...

I assume the app must use another method to engage with the network and not the MAC, how can we do this?

Swiftnesses commented 5 years ago

@andrasj I'd love to somehow implement the confirmation event into my Node JS script, is this returned via CSRmesh, or do I need to use something else? Did you turn anything else up with regards responses, it's obvious the app has little / no issues and seems to work pretty well tbh!

@nkaminski do the responses above make sense to you?

kmidt commented 5 years ago

Hey Guys. Any Solution ? When not Move is dead in my House in FHEM :)

wasbaun commented 5 years ago

Hey, Iam new to Github und following this project quite a while. I have two Move Units and had it up and running with csrmesh und raspberrypi. Today I received a Mail from OmniaBlinds, that they are not selling them anymore and that I can buy a newer better blind motor from them.... The teptron website is under construction now. Now I want to contribute to this project, because from now on, we are on our own and I dont want to throw the units to the trash. Invested to much money. As I said, I the move units worrk with raspberrypi and openhab. I use one of the experimental branches oh this project that worked for me. But I have the problem, that the units forget their start and stop position. So I think the only solution would be a firmware hack or use one of the uart commands to change positions.

nkaminski commented 4 years ago

This issue has been idle for quite some time; is there still interest in advancing this given that the move units are no longer readily available?

lisaele commented 4 years ago

Yes, I'm still interested. My move worked great in Home assistant before I upgraded to the new firmware. Been searching google to see if there is a way to flash the old firmware back on the Move but no luck. Any progress on this would be much appreciated!

andrasj commented 4 years ago

Short answer: yes Longer answer: I think the real problem is not clearly defined, there are conflicting reports that csrmesh is/isn't working with old/new firmware of the devices. It seems some people keep trying stuff on their own. I cannot spend time on this project at the moment, so I'm passively following this thread for now.

To be honest, I'm afraid that one day, the official app will no longer work (on newer phones), but it is still needed for initializing the meshnetwork and pin (at least afaik). For this reason, I already hoped someone knew a way to replace the firmware of the device. I think most of us only need a BLE/IO-gateway and could do automations from another system. With a 'simple' open source FW (if possible at all on csr-chips), it would be much easier to develop/integrate the product. I'm willing to open up or provide one of my devices for reverse engineering to someone that can help with this. IIRC the proprietary csr-mesh stuff is all done in the csr-SDK and doesn't need special hardware, which could mean the controller/BT-module could be reused without the mesh-stuff.

nkaminski commented 4 years ago

Open source replacement firmware is an interesting thought.

However as I don't have a move unit myself and therefore don't know anything about the hardware platform used, I would be dependent on someone with one to take a few internal photos and provide visible part numbers or similar hardware identifiers. That should give us an idea of how easy or difficult it would be to develop and flash a replacement firmware.

That being said, it sounds like the current major issues interfacing with the proprietary V2 firmware are the fact that the MAC address changes after every boot and that the provisioning process requires the now-unsupported app. Agree?

andrasj commented 4 years ago

about interfacing with v2, the changing MAC is an issue, but since the network still advertises itself as 'MOVE', it is possible to implement a workaround. My main problems were: -unreliable communication (sometimes multiple retransmits are needed before the device starts moving) -lack of documentation of the protocol to set speed or read data.

about the hardware: some documents can be found on https://fccid.io/2AICLM1508 , the original crowdfunding campaign mentioned CSR1010 , in the user manual the technical section says: Primary MCU chip: CSR1010 Secondary MCU chip: Atmel ATtiny48 These pictures are not really clear, but it's a start.

andrasj commented 4 years ago

Meanwhile I opened up one of my devices, see attached for pictures with more detailed components. The motor seems to be standard DC, for positioning there is a half plastic disc attached to shaft. I guess the optical sensor is on the motor/IO pcb. Maybe I'm gonna try to control it with an ESP, so there is direct wifi-access. (but I'll stop hijacking this thread, people who are interested or are willing to help can contact me) MOVE_Battery-IO-Board MOVE_ControllerBoard

nkaminski commented 4 years ago

@andrasj If you have access to a multimeter: when assembled and powered with batteries or USB, what voltage level do you see between the leftmost and 4th from left as well as leftmost and 5th from left pin (in orientation of photo) in the pin header that is partially visible at the top right of the main board?

From your photo, I can see that the pin count as well as location of the ground pin on that header is consistent with the FTDI style serial pinout.

If this is indeed a serial header, it is very possible that this port may still be active even though USB serial has been disabled.

andrasj commented 4 years ago

the 2 outer pins seem to be connected, they had exactly 0V, between the left and the middle 4 pins it was kind of floating between 20-30mV. When measuring while powering up, I could see a short peak of higher voltage (or it might be an artifact of my simple multimeter). If it's a serial, I guess I should be able to measure 0 Ohm between the pins and the Rx/Tx pins from one of the controllers?

nkaminski commented 4 years ago

Correct regarding the fact that you should see zero ohms resistance between the serial pins on the header and the respective microcontroller pins.

However, my suggestion to measure voltage was based off of the fact that an enabled but idle TTL serial port will drive it's Tx line high. Therefore it looks like this either isn't a serial port or isn't active.

andrasj commented 4 years ago

I looked for the open contacts, it seems they are debug/programming headers for the controllers. The ones in the corner next to the USB-connector are debug lines for the CSR-chip: 1 -> CSR pin GND 2 -> CSR pin 18: DEBUG_CLK : debug SPI CLK selected by SPI_PIO# 3 -> CSR pin 19: DEBUG_CS# : debug SPI chip select (CS#) selected by SPI_PIO# 4 -> CSR pin 20: DEBUG_MOSI : debug SPI MISO selected by SPI_PIO# 5 -> CSR pin 22: DEBUG_MISO : debug SPI MISO selected by SPI_PIO# 6 -> CSR pin 26: SPI_PIO# : Selects SPI debug on PIO[8:5]

The ones around the atmel are the debugging lines for the ATTiny, and according to the datasheet they can be used for serial programming the chip. 1 -> AT pin 25: PC6 (RESET/PCINT14) 2 -> AT pin 15: PB5 (SCK/PCINT5) 3 -> AT pin 13: PB3 (PCINT3/MOSI) 4 -> AT pin 14: PB4 (PCINT4/MISO) 5 -> AT pin 4: GND 6 -> AT pin 3: VCC

nkaminski commented 4 years ago

Atmel MCUs are very familiar to me, and these are exactly the lines you need to read and write the flash on such. You will need a 3.3v logic level Arduino or avrisp and the avrdude utility (open source) to do so.Also makes me wonder if all/most of the motor control functionality is implemented on the attiny and if the SPI bus is also used for communication between MCUs.NashOn Feb 8, 2020 12:09 PM, andrasj notifications@github.com wrote:I looked for the open contacts, it seems they are debug/programming headers for the controllers. The ones in the corner next to the USB-connector are debug lines for the CSR-chip: 1 -> CSR pin GND 2 -> CSR pin 18: DEBUG_CLK : debug SPI CLK selected by SPI_PIO# 3 -> CSR pin 19: DEBUG_CS# : debug SPI chip select (CS#) selected by SPI_PIO# 4 -> CSR pin 20: DEBUG_MOSI : debug SPI MISO selected by SPI_PIO# 5 -> CSR pin 22: DEBUG_MISO : debug SPI MISO selected by SPI_PIO# 6 -> CSR pin 26: SPI_PIO# : Selects SPI debug on PIO[8:5] The ones around the atmel are the debugging lines for the ATTiny, and according to the datasheet they can be used for serial programming the chip. 1 -> AT pin 25: PC6 (RESET/PCINT14) 2 -> AT pin 15: PB5 (SCK/PCINT5) 3 -> AT pin 13: PB3 (PCINT3/MOSI) 4 -> AT pin 14: PB4 (PCINT4/MISO) 5 -> AT pin 4: GND 6 -> AT pin 3: VCC

—You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub, or unsubscribe.

andrasj commented 4 years ago

Thanks for the quick feedback, I'm not familiar with atmel (little experience with PCI & ESP), but it looks like I could use/flash a spare ESP (which is 3.3V) to use as an avrisp. There is even some hope for flashing the CSR-chip: https://github.com/lorf/csr-spi-ftdi

Based on looking at the pcb-traces & datasheets I'm currently asuming: -CSR & Atmel are communicating over I2C (or SPI? pins are overloaded on CSR) -datapins of the usb-connector for power are connected to UART RX/TX of CSR-chip -CSR-chip is handling BLE/battery/(solar/)temperature monitoring/automation rules -ATTiny is controlling the motor/encoder (I'll try to verify some of these assumptions with the multimeter)

There are several things which could be done: -sniff between atmel & csr (maybe some correlations with datapackets sent over BLE which could help debugging/reverse engineering the protocol) -forget about the csr & put another comms-module in front of the atmel (if that protocol is understandable) -same as above but with custom FW in atmel (which will require further analysis of the electronics for motor control) -custom FW on csr (but need to get the SDK and experience of programming BLE)

Only the first idea could help people who don't want to open up their device (and maybe the last if we could find a way to upload the FW over serial/usb). And since the shell of the device is glued together it won't be easy to open up all devices to get close to the hardware to modify or reflash.

Sometimes I'm thinking it's easier to rebuild it from scratch, but at least this way I learn new stuff and I am having fun :-)

Maatss commented 4 years ago

Two years later.. This might speed things up!

MoveDeviceConstants byte ALLOC_SUN_AUTOMATION = Byte.MAX_VALUE; byte ALLOC_TEMP_AUTOMATION = -65; byte ALLOC_TIME_AUTOMATION = 63; byte AUTOMATION_TYPE_SUN = 1; byte AUTOMATION_TYPE_TEMP = 2; byte AUTOMATION_TYPE_TIME = 0; byte CALIBRATE_CLOCKWIZE = 35; byte CALIBRATE_COUNTER_CLOCKWIZE = 36; byte FULLY_CLOSED = -1; byte FULLY_OPEN = 0; int MOVE_1_APPEARANCE = 4192; int MOVE_2_APPEARANCE = 4352; byte MOVE_AUT_GET_AUTOMATION_LIST = 80; byte MOVE_AUT_GET_MOVE_TIME = 82; byte MOVE_AUT_GET_SENSOR_AUTOMATION = 88; byte MOVE_AUT_GET_TIME_AUTOMATION = 86; byte MOVE_AUT_REMOVE_AUTOMATION = 89; byte MOVE_AUT_SET_MOVE_TIME = 81; byte MOVE_AUT_SET_SENSOR_AUTOMATION = 87; byte MOVE_AUT_SET_TIME_AUTOMATION = 85; byte MOVE_CMD_CALIBRATE_CLOSE = 114; byte MOVE_CMD_CALIBRATE_OPEN = 112; byte MOVE_CMD_ECHO_REQUEST = -32; byte MOVE_CMD_ECHO_RESPONSE = -31; byte MOVE_CMD_GET_DEVICE_NAME = 66; byte MOVE_CMD_GET_DEVICE_STATUS = 64; byte MOVE_CMD_GET_STATUS = 22; byte MOVE_CMD_GOTO_GROUP_PRESET = 68; byte MOVE_CMD_MOVE_POSITION_ON_TIME = 70; byte MOVE_CMD_MOVE_REBOOT = 41; byte MOVE_CMD_MOVE_TO_POSITION = 34; byte MOVE_CMD_SET_DEVICE_NAME = 65; byte MOVE_CMD_SET_GROUP_PRESET_POS = 67; byte MOVE_CMD_SET_MESH_WAKE = 69; byte MOVE_CMD_STOP_TURNING = 33; byte MOVE_DEVICE_NAME_MAX_LEN = 20; byte MOVE_GET_STATUS_RSP = -106; int MOVE_HORIZONTAL = 1; int MOVE_HORIZONTAL_TILT = 2; byte MOVE_SET_POS_ACK = -94; byte MOVE_STATUS_INVALID_ID = 1; byte MOVE_STATUS_NOT_TIMESYNCED = 3; byte MOVE_STATUS_NO_MEM = 2; byte MOVE_STATUS_OK = 0; byte MOVE_STATUS_REQ_INCOMPLETE = 4; int MOVE_VERTICAL_CENTRE = 4; int MOVE_VERTICAL_LEFT = 6; int MOVE_VERTICAL_RIGHT = 7; int MOVE_VERTICAL_SPLIT = 5; int MOVE_VERTICAL_TILT = 3;

Wake up procedure Runnable wakeBurst = new Runnable() { public void run() { if (mBurstCount <= 32) { ByteBuffer buffer = getFrameBuffer(6); buffer.put(MoveDeviceConstants.MOVE_CMD_SET_MESH_WAKE); buffer.put((byte) 100); buffer.putShort(180); buffer.put((byte) 4); buffer.put((byte) -1); sendMeshFrame(0, buffer, false); mBurstCount++; mWakeBurstHandler.postDelayed(wakeBurst, 357); return; } stopWakeBurst(); } };

Note Should be noted that I have not verified this apart from recognizing a couple commands, such as: byte MOVE_CMD_MOVE_TO_POSITION = 34;