I have bought Orvibo S20 (picture) smart socket. You can find them on Amazon, eBay and probably many other online shops. The socket comes with an app for Android and iOS that is used to control the socket. Unfortunately, the app is proprietary and also not available for normal computers. I wanted to have some free software solution. Also, the original app didn’t work too reliably, and of course you can’t fix it without having a code. Again, this shows why it is important to have free software…

After searching a bit I found some code on GitHub written for Ninja Blocks. It also came with some reverse engineering data (I will refer to this as the original reverse engineering later and will assume that you briefly looked at it). That file might look slightly scary initially if you are not used to that kind of stuff but actually everything is quite simple. It seems that the socket can be controlled by simply sending UDP packets over the network and listening for replies. You can even try to play a bit with netcat but of course it is not too convenient. So I decided to write my own program using Qt 5. It provides a lot of convenient functions in its QtNetwork module and also it would make it easy to write GUI if I ever decide to do so in the future. Also, I’m familiar with Qt because it is used by KDE Applications. Another reason for choosing Qt was it’s support for sockets and slots and I expected them to be useful.

As you can see in the reverse engineering file, there are commands to discover the socket, subscribe to it (which is required before doing anything else), power it on/off and read some tables (Socket Data contains information about the socket and Timing Data stores when to turn the socket on or off). They all follow similar pattern. You have to send

Magic Key+ message length + command id + rest of the message

where Magic Key is 68 64 (hexadecimals) and is used to distinguish these UDP packets from any other packets that are send over UDP port 10000. Every time you send a message the socket replies with another message confirming the action of the first message. Or the socket doesn’t reply. We are using UDP protocol for networking. So there is no guarantee that message is received and later I had to write some code to make sure packets are received. Hence, I implemented message queue and resend every command until I get a proper reply before sending another command. This finally made my program more reliable.

Writing Socket Data

I quickly managed to get some basic stuff working (for example powering it on and off) and soon I implemented most of the commands from the file with reversed engineered commands (reading Timing Table is still not completed but shouldn’t be too hard). Since I wanted to do more than that, I started Wireshark and analyzed a few more packets. I quickly learned how to write Socket Data Table too. Apparently, you send command very similar to what you receive when you request Socket Data but with different Command ID (74 6d instead of 72 74 in hexadecimals).

So to write Socket Data I send the following packet

Magic Key + message length + 74 6d + mac + mac padding + 00 00 00 00  + AA 00 BB + recordLength + record;

where

record = 01 00 /* record number = 1*/ + versionID + mac + mac padding + reversed mac + mac padding + remote password + socket name + icon + hardwareVersion + firmwareVersion + wifiFirmwareVersion + port + staticServerIP + port + domainServerName + localIP + localGatewayIP + localNetMask + dhcpNode + discoverable + timeZoneSet + timezone + countdownStatus + countdown + 00 (repeated twelve times) + 30 (repeated 30 times, note that hex 30 corresponds to 0 in ASCII);

countdownStatus is 00 ff when countdown is disabled and 01 00 when countdown is enabled.

AA 00 BB is actually table number and version flag. E.g. 04 00 01. 4 stands for table number (Socket Data is Table number 4) I don’t completely understand what is version flag, so if you know please tell me in the comments.

Then socket replies with:

Magic Key + message length + 74 6d + mac + mac padding + 01 00 00 00 00;

Now just send an already documented Socket Table packet (see: http://pastebin.com/LfUhsbcS) to update your variables.

Writing Timing Data

Writing Timing Data is exactly the same (even Command ID is still 74 6d) as writing Socket Data but you must specify 03 a a table number

Magic Key + message length + 74 6d + mac + mac padding + 00 00 00 00  + AA 00 BB + record1Length + record 1+ record2Length + record2 + record3Length + record3 + …;

record again contains the same data as what socket sends when you request timing data.

Initial pairing of the socket

The authors of the original Ninja Blocks orvibo-allone driver assume that socket was already paired using the proprietary Android/iOS application. Their original reverse engineering also contains no information how to do that. I expected that this might be a bit tricky to do because unpaired socket is not connected to the router and you have to somehow transmit your wifi configuration into the socket. I think there are at least two ways to pair that proprietary Android/iOS app implements. If you press the socket button for a few second it switches to a rapidly blinking red led mode. Then long press it again and it switches to rapidly blinking blue led and the socket creates an unencrypted wifi network (it was called WiWo-S20).

Then I created the wifi network with the same name on my laptop and tricked the proprietary app into believing that it is the socket’s wifi network. I was able to intercept the following message on UDP port 48899 (everything is in ASCII in the section, not in hex):

HF-A11ASSISTHREAD

So apparently, Orvibo S20 has HF-LPB100 Wifi chip inside. This chip can be controlled by the AT+ commands (you can find them online but I will write a brief summary here) and I was able to do initial socket configuration!

  • Switch S20 to rapidly blinking blue led more. Connect your computer to WiWo-S20 network.
  •  Send “HF-A11ASSISTHREAD” on UDP port 48899 to the broadcast address (don’t include ” in the message).
  •  S20 will reply with “IP address,MAC Address,Hostname”. The socket always replies to the same port as the source port of your message.
  • Acknowledge that you got the previous message by sending “+ok”.
  • Send “AT+WSSSID=ssid\r” where you replace ssid with your WiFi network name. \r is the carriage return (CR) symbol.
  • The socket will reply with “+ok\n\n” (\n in this case is carriage return + line feed) if everything is correct or “+ERR\n\n” if something is wrong.
  • Send your Wifi security settings: “AT+WSKEY=WPA2PSK,AES,PASSWORD\r”.  The socket will again reply with “+ok\n\n”.
  • Switch HF-A11 chip to station mode by sending “AT+WMODE=STA\r”. Again, wait for “+ok\n\n”
  • Reboot your socket with “AT+Z\r”.
  • Connect your computer back to your router. Wait until the socket boots. Now you can find it using normal discovery packet on port 10000, then change socket name, timezone, etc. with Write Socket Data packet…

I did some investigation and it seems that we need to send a slightly modified Table Data and Socket Data packets immediately after pairing to set them to default values. More information will be published later.

Another way to pair the socket from the rapidly blinking red mode. It is slighly less reliable than this method but on the other hand does not require you to disconnect from your wireless. Actually, it doesn’t require your computer to have any wireless at all.

Unfortunately, it seems that either way WPA encryption key is transferred in an insecure way, i.e. the socket is not able to use any public key cryptography. Slightly safer way to do it manually is to first change your WPA key to something temporary and pair the socket. Then use AT+ commands to change WPA password to the real one and change your router’s WPA password back.

Also, note that this socket doesn’t support WPA Enterprise. So if you would like to use it at home then create two Wifi networks: WPA-PSK for the socket and WPA-EAP for everything else (OpenWrt can do this easily).

Code

I released all code under the GNU General Public License version 3, so the code is freely available to everybody. Git repository is available at:

https://git.stikonas.eu/andrius/s20 (feel free to create an account here and fork the code)

Windows binaries

I compiled windows binaries. There is also a very limited GUI that does not yet have all the features of console app but if you prefer GUI then it might be useful.

Console 64-bit 32-bit
GUI 64-bit 32-bit

Donations

If you find this work useful then tips are very welcome. You can send Bitcoin tips to bc1qe2dfqjwgse5v6cl6rhtk352ru90t0hnve45f2c.

I was able to buy the second socket which already resulted in improved multiple socket support. Thanks for the donations!

Become a patron Donate using Liberapay Bitcoin: bc1qe2dfqjwgse5v6cl6rhtk352ru90t0hnve45f2c

Bugs

Bugs are tracked in the Gitlab issue tracker.

See also

Go code by Grayda (basic support for S20 but also supports Orvibo AllOne devices)

PHP code by Fernano Silva (supports most features of S20). See also his technical data file.

Perl code by Branislav Vartik

331 thoughts on “Reverse engineering Orvibo S20 socket

  1. Have you done any hacking with the Namaco SWA1 wifi switch? I’d like to be able to up change out the firmware to match my Sonoff wifi switches, but they did not label the interface connections on the board.. I’ve got pictures and if needed I’ll send a SWA1 along.

    Reply
  2. Thanks for this writeup. I am not a coder or programmer in any way, I just wanted to ask if there is a simple IP command that can be used to either set the S20 power to on or off, or toggle the power? I want to be able to control my S20 socket from DemoPad which is a home automation software (that enables iPad control) that can send IP commands and IR commands. Any advice would be appreciated.

    Reply
    • You need 2 commands. First you need to send subscribe command to UDP port 10000. And then Power on or power off. Look here https://pastebin.com/LfUhsbcS. Each command in this pastebin file has SEND section and HEX string. This is what you need. You need to replace MAC address with your MAC address though. Also DemoPad seems to require \x before each hex digit. So instead of 68 64 00 18 63 … You’ll need \x68 \x64 \x00 \x18 \x63 …

      Reply
  3. One possibility is to start using Sonoff S20 after flashing it with ESPEasy firmware. Combining software of opensource project around ESP8266 wifi chip with hardware which is deliberately left to be easily hackable from vendor is giving much expected desired result 🙂

    Reply
    • Thanks! This might be useful for some people. And it does not depend on any library, so indeed very portable. Although, that makes code much longer but that’s expected…

      Reply
  4. Hi , Andrius – thanks for opening up this protocol!

    can s20.exe be run from a batch file with arguments?
    I just want to make a .bat file to toggle the socket on and off.
    I have unsuccesfully tried:
    s20.exe /p
    and
    s20.exe -p

    Reply
    • Not easily. You can try to do input redirection… s20 program is not too suitable here because it tries to detect all available devices, it is not easy to select a particular one…

      Probably easier to use other scripts, e.g. check perl script in “see also” section. You can hardcode IP and MAC there, so you won’t need to do initial discovery.

      And a lot of credit should go to other people too who were figuring out the protocol. I only did some parts…

      Reply
      • Thanks – I have had no luck trying all the other scripts out there.
        I tried using the UDP library in processing, but can’t get it to work.
        Your exe is the only thing that works for me.

        I will try to modify your code to create a simple “toggle power and exit” exe.
        What ide/compiler do you recommend for compiling your c++ code?

        Reply
        • Probably QtCreator might be easiest on Windows (even though I use KDevelop on GNU/Linux and even these .exe files here are cross compiled with mxe).

          If you try to modify it you probably need to significantly rework consolereader.cpp file where input handling is. Server and Socket classes would hopefully be usable without any modification.

          Well, my program has some optimizations for UDP as used in this socket. It makes sure message was received and if not then tries again a few times. But again, not everything is perfect in my program, I didn’t have enough time to do everything I wanted.

          Reply
          • Thanks again,
            I tried QT and although I’m not that experienced in c++ I was able to modify your code to create 3 exe files: s20_TOGGLE, s20_ON and s20_OFF. Fast, simple and they work every time.

            These work as tools that I can launch from Processing to get the job done.

            Two problems remaining – I can’t find a way make QT force the command window to close itself so the tools can be run unnatended – and the big problem:
            It’s really hard to get a working release build out of QT.
            Many arcane tools are needed outside of the IDE using windows path environment variables / dll dependencies that I’m too stupid to master as a Windows user 🙂
            As for exporting a fully functioning standalone static EXE similar to yours – that looks really hard!

          • Well, as non Windows user I’m not really sure about command line window on Windows. But perhaps you can try removing console flag in s20.pro file.

            Well, if you publish the source (you can even fork it on https://git.stikonas.eu), I can compile statically linked .exe files. I use mxe scripts, so it is mostly automatic, although still takes a while to compile all library dependencies for windows from scratch.

            Although, it would be nicer if those new .exe work in general case, not just your IP/MAC. Perhaps you already did that? E.g. allow specifying it on the command line.

  5. Hi ! My final goal is to control S25(US) by programming Raspberry-pi instead of using an application. So before doing that I am trying to program a simple code in a OS computer(before setting it into Raspberry-pi) that could send data or any message to the socket S25 these two(computer S25) can communicate using wifi. I am a starter in programming and have difficulty starting this project. I think your post is related to what I am trying to do, but I am not quite sure where to set the codes and have trouble understanding how to start. Also, is your instruction available for S25 socket? Any help or comment would be very helpful. Thank you.

    Reply
    • I don’t think my instructions work for anything else than S20, I never owned other sockets. A few comments bellow there is some talk about B25. Is B25 same as S25? I have no idea… So apparently the protocol for B25 is similar but it is not the same, it is modified. Well, if you want to compile my code on Linux distro (e.g. on Raspberry Pi or your other computer) you need to install cmake and also Qt. The process depends a bit on what distro you are using… So knowing it would help me to give more precise instructions. If you want to modify my program eventually you’ll need to learn a bit of Qt. There are various tutorials online.

      Reply
      • I loved your library! however now on Aliexpress S20 is not available anymore, only B25.. (When) will you add support for that latter one? thanks.

        Reply
        • Well, things are a bit complicated. Right now I’m writing up my PhD thesis and have my thesis defence in July, so I definitely can’t do any work on it right now. And after July it’s very hard to tell what will happen. Can’t promise anything right now… And also my PhD scholarship has ran out a couple of months ago, so that also doesn’t help with respect to buying tech stuff…

          And I also don’t have any B25 sockets… I only have two S20 sockets either, One was bought with the donation here, so I was able to fix a few remaining multi-device bugs.

          P.S. you can still buy S20 devices on ebay.

          Reply
          • Hey! thanks a lot for your commitment. I wish you all the best for your PhD, I’m sure you’ll do an awesome job. and I will check out ebay then, I guess 🙂

  6. I’ve seen a few comments here regarding newer Orvibo products such as the B25 or the Coco.

    I’m the author of node-orvibo (a node.js library for controlling Orvibo products), and have had someone (Karl, who I believe commented here) order me a B25 to test, so once I get that, I’ll hopefully have something working. When I do, it’ll likely be released as node-orvibo2.

    For those wondering, newer devices use a slightly similar protocol to the older products (still using the familiar “6864” magic word at the start), but they now use AES encrypted JSON and a CRC32 checksum. If you check out node-orvibo, a recent commit has some tools that let you encrypt and decrypt packets. That’s as far as I’ve got, but it’s a massive leap forward.

    As always, I’m looking for people who can assist with the project so I can write up proper documentation for everyone to use

    Reply
    • Having a proper documentation is probably quite important. With S20 it is unfortunately a bit of a mess. There is that original pastebin, some documentation in your repo, some info about pairing here… Some other documentation in orvfms repository which contains information that your docs don’t have (e.g. DST stuff, fractional timezones).

      Maybe some kind of wiki solution where many people can edit would work better than keeping docs in personal repos?

      By the way, this is something with which non-programmers can help. There are probably people willing to help but who don’t know how to program. Trying to merge various bits of information from various sources and producing single more complete documentation might be helpful.

      Reply
      • Hi guys,

        I’m part of those people that don’t know (yet) how to program, but interested to learn and who is willing to help. Let me know how I can help you.

        I’ve installed openhab on one of my rapsberry and started playing a bit with it. I’ve bought a few Orvibo S20 and Coco.

        Reply
        • Well, it depends on what you want to do. Some things don’t require any programming at all, e.g. improving documentation (currently there are a few files, some newer, some more outdated but scattered around, it’s not in a single place) or trying to understand the protocol that those devices use (e.g. I never had Coco device, so not sure if it’s the same or not). I haven’t use openhab myself but looks like there is some orvibo s20 support there (https://github.com/erangaj/openhab2-orvibo) but not Coco. I guess Coco uses different protocol. So if you are interested you can try to understand the difference between S20 and Coco. Wireshark program is particularly useful for this purpose. Well, if you want to improve one of these orvibo projects, you might try to learn programming… But they are all written in different programming languages… E.g. openhab-orvibo in Java, my program in C++, some other ones in PHP or Go… So first thing is you have to decide on what do you want to do/learn…

          Reply
  7. Hello Andrius,
    ¡Really a great, great, job!
    I’m trying use a Orvibo B-25 (with ground connector), but it doesn’t work, maybe it uses another Wifi chipset…
    Could you provide me any help about this?

    Reply
    • Probably another… See a short discussion a few comments bellow this. If you have some time you can try to use Wireshark and see what it uses. But I was told that it now uses TCP ports instead of UDP, so most likely completely different protocol.

      Reply
  8. Hello!
    Thank you for excellent post!
    Can you show me on my error?
    I’m doing the same, but when I send WSKEY data, the switch always answers “+ERR=-4”
    Please find a screeenshot from network utility. http://prntscr.com/dtet3l

    Reply
  9. Thanks, excellent post.

    Do you know the needed changes or anyone that has implemented it for the Orvibo Coco Smart WiFi Power Strip?

    Thanks

    Reply
    • I’m not sure… It might be completely different protocol. I just don’t have device. E.g. somebody said Orvibo B25 devices are controlled via TCP commands. It shouldn’t be too hard to reverse engineer if somebody has a device and a little bit of free time.

      Reply
  10. Hi,
    I have a couple of S20s that I am successfully controlling via a raspberry Pi. I achieved this about a year ago following some very helpful advice from this blog.

    I have now bought an Orvibo B25 in the hope that it will work in exactly the same way (or at least a very similar way) as the S20 but my php file does not work. Obviously I have changed the IP address and the MAC address. Has anyone tried to use the B25? Externally it is very similar to the S20 and seems to be marketed as a more updated version of the S20. Does anyone know what else I need to change in order to use the B25 in a similar way to the S20?

    Reply
      • Thanks Andrius,
        I’m far from expert at Wireshark – but happy to learn.
        I have Wireshark on my PC but this does not see my S20 traffic. I assume this is because I only see traffic at the PC’s Ethernet card and so do not see traffic between the raspberry Pi and the S20 (even though I use SSH on the PC to instruct the raspberry Pi to talk to the S20!). An alternative would be to run Wireshark on the Pi (too big an ask since I’m running it headless!) or get Wireshark on the PC to see the wider LAN and not just its own traffic (is this possible?).
        Another idea would be to install PHP on my PC so that I can generate traffic between the PC and the S20. I think this is my next thing to try.
        Or maybe use WiWo on the PC but I’m not clear that it’s possible.

        Reply
        • Do you have a WiFi card on your PC or laptop?

          So I used my WiFi card as access point instead of the router. On Linux this can be easily accomplished with NetworkManager. Not sure about other OSes though. Than I used WiFo app on my phone paired to my laptop’s WiFi AP. So basically laptop was between my phone and S20 socket. That made Wireshark see traffic.

          By the way, I haven’t really used Wireshark before this either. So I’m not an expert either. But it was easier than I initially expected.

          Reply
          • I also want to get this working on B25 units.
            However, I did wireshark captures, and traffic is now on TCP, rather than UDP, so I assume the protocol is rather changed now!
            Hopefully someone with more skills than me can decode and implement ….

  11. hi

    i contact the support many time but unfortunately my switch is still not working over GSM network
    who can assist?

    Reply
    • Yeah, accessing the socket from outside your local network is very unreliable.

      I would suggest getting some small server (you can buy something like Raspberry Pi quite cheaply) and then you can use for example that PHP program by Fermando Silva and access your socket over web browser.

      Well, that requires some more time because you need to install GNU/Linux and a webserver but there are plenty of guides online, it’s not that hard.

      You can also try opening UDP port 10000 in your router. Sometimes it helps people but not always.

      Reply
      • hi

        thanks for your replay
        but to open a port i need to know what the IP address of the device, and i am working on DHCP.
        can i give the device a static IP?

        Reply
        • 1) You can see mac addresses in your router settings (but the location depends on router firmware).

          2) Or you can download my S20 program (actually you’ll need command line version which shows more info than GUI version) run it and it will display socket’s mac address.

          Reply
          • you can do what i just did. in the router, you can find the dhcp table, usually in the status tab. this table lists all the IPs currently distributed by the router, as well as the MAC address of the device it was given to.
            if you can see the names there, try looking for HF-LPB100. that should be the orvibo device.
            if you want to make sure, or don’t have the names (or have multiple orvibo devices), try unplugging the device from the power and waiting for the dhcp table to get refreshed, then see which device is no longer there. if you don’t want to wait, you could try pinging all devices until you hit the one that doesn’t answer anymore. then plug the device back in the power, and ping it again to make sure it is really it.

  12. Hi – thanks for this. Really useful info.
    I know this is probably a bit lame – but I haven’t found a way of sending the UDP packets for the initial pairing. I’ve spent quite a while looking and trying various things (telnet, putty, nc etc.)
    What’s the best / easiest way of sending the AT commands and receiving the responses from a raspberry pi / debian or Windows 10 machine?
    Many thanks
    Jon

    Reply
    • Well, you can always use my command line program. It supports both methods of pairing. You only need to do it once. You can try to use netcat if you want but it is more complicated…
      You can also try to use bash directly, but I don’t think you will be able to see what socket sends you back, so you’ll have to work “blindly”, e.g. echo -n “HF-A11ASSISTHREAD” >/dev/udp/localhost/48899

      After that you can use whatever tool you want to manage the socket…

      Reply
  13. After power cut orvibo doesn’t switch on automatically, is any way to force auto start after power failure?
    Regards

    Reply
    • No. Socket does not remember it’s previous power state before the power off. Only socket data (passwords, names, time zone) and timing data (e.g. what time of the day or week should the socket turn on, off)

      Reply
      • If the socket does not remember the power state, how it knows it should be OFF after power cut? Is there any way to change this default OFF behaviour to ON?
        Thanks!

        Reply
        • Well, it’s probably hardwired into socket logic. And no, I don’t think there is any way to change default behaviour from OFF to ON. By the way, if there was a way to change default power state than that would be the way to remember the power state…

          Strange, why do I get so many questions about power cuts? I’ve never experienced any power cuts here myself. Well, maybe in some countries they are more common…

          Reply
          • I’ll give you my example: bathroom fan attached to S20 which is attached to bathroom lighting. I want bathroom fan to be switched on when I turn the lighting on and when I want switch it off from the app. When you take a shower it’s not a big deal to hear the fan noise but when you want to take a bath relax and you want to enjoy the silence lol 🙂

    • Hello, i would like to ask if its possible to turn on/off a specific socket by its IP/MAC Address from the command line

      Ex: s20.exe /s 192.168.1.10 /a on

      Would be really useful in integrating with home automation stuff

      Reply
      • Well, my program is probably overkill for that. And it was mostly designed to be an interactive program… In principle you can still try to turn them on/off using input/output redirection but again this is more complicated than necessary. I would suggest using something much simpler… You can try that perl script in “See also” section or simply send the required UDP packet using netcat.

        Reply

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required

Time limit is exhausted. Please reload CAPTCHA.