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;
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):
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).
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)
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.
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!
Bugs are tracked in the Gitlab issue tracker.
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.
340 comments on “Reverse engineering Orvibo S20 socket”
Sveiki, ar galima būtų jūsų paprašyti perprogramuoti S20 (turiu porą vienetų) kad pavyktų suintegruoti su Google home, iftt?
Orvibo S20 neįmanoma perprogramuot (bent jau namų salygom). Kiek man žinoma, iš visų protingų rozečių/jungiklių perprogramuojamos yra tik tos, kurios naudoja ESP8266 arba ESP33 čipus (https://templates.blakadder.com/ juose galima įrašyt Tasmota arba ESPHome). Beje, jei pas just Sonoff S20, o ne Orvibo S20, tai galima Tasmotą įrašyt, bet turbūt turite Orvibo S20…
Ką galima būtų parekomenduot su Orvibo S20, tai (namie, ne debesyje) veikiantis Home Assistant. Tai pakankamai galinga namų automatizavimo sistema.
With the upgrade to iOS14 the official WiWo app does not work now…
No surprises there – when you try to set on and off timers it just crashes – and guess what – no way to contact them to advise them.
I am here to find a really quick and hacky way to use Cron to send on and off commands..
I will use Cron to use my timers now, but would love to work out how to do this in linux command line… or an app to just send an on and off command …
would be nice to have a simple ‘on’ and ‘off’ script with a parameter for the socket number so I can just call it from bash, or in cron 🙂
any thoughts on the easiest way to do this.
The poor goldfish are getting very sporadic light time now – as we have just entered Daylight Savings, and every time it mucks with the time zones. 🙁
You can try that Perl code in the see also section by Branislav Vartik, it can already do what you want.
But at some point it might be worth investing some time in installing full home-automation solution (e.g. Home Assistant, OpenHAB, etc…).
Oh thank you so much,
I did not see that perl script down there… it works amazingly well 🙂
Thank you again for pointing it out to me..
I am not allowed to run HA or OpenHAB 🙁 — Partner hates home automation, and she only tolerates the Fish Tank light because she keeps forgetting to turn it on.
Yes drives me mad – but what you going to do 🙁
> but what you going to do 🙁
Change partner?! xD
You’re not allowed xD I can’t believe what am I reading 🙂 Carry on and good luck man!
These sockets stopped working properly for me last year, this might help https://github.com/chrisbyrneham/S20-Life-Extender it’s a little Arduino ESP8266 sketch that will synchronise the time on the old S20 sockets, now that the Orvibo time server for them seems to have been decommissioned around mid 2019.
You can still use the Wiwo app to program them.
Well, for some people it might be useful. But you can do similar things with any Linux server, no need to buy Arduino if you already have some always-on machine on your home network.
Another way to fix time server is to go to your router
and port forward UDP destination port 123 for packets originating on your LAN to your own NTP server (e.g. the one running on your router).
Something like this worked for me OpenWrt
iptables -t nat -A PREROUTING -i br-lan -p udp --dport 123 -j DNAT --to 192.168.1.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.
No, I haven’t done anything besides S20…
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.
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 …
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 🙂
Why are they all using “S20” as name…
Possibly interesting: http://antinode.info/orvl/orvl.html
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…
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:
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…
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?
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.
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.
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.
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.
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.
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.
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 🙂
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
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.
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.
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…
¡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?
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.
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
Might be that you didn’t include \r at the end of your message. Try and see if it helps.
Thanks, excellent post.
Do you know the needed changes or anyone that has implemented it for the Orvibo Coco Smart WiFi Power Strip?
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.
If I send you a b25 plug, would you try to do it?
This year I will be quite busy, have to write my PhD thesis… Maybe try some other guys who worked on Orvibo S20 (e.g. from the “See also” section)?
Ok, thanks…good luck with your work.
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?
Maybe you can try using Wireshark to figure out what is changed B25 protocol? It might actually be completely different protocol if they use some other chip.
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.
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.
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 ….
i contact the support many time but unfortunately my switch is still not working over GSM network
who can assist?
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.
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?
Yeah, usually on the routers you can make it always assign same IP address sticky.to certain MAC address.
how can i know it MAC address?
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.
can you please send me a link to your program ?
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.
that users can control multiple socket with a s20? (My wife and I)
Yes, multiple users can control multiple sockets of s20.
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?
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…
After power cut orvibo doesn’t switch on automatically, is any way to force auto start after power failure?
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)
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?
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…
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 🙂
Looks cool. On Geekbuying they have many products from Orvibo on sale.
Congratulations, excelent post ; )
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
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.