SonOff without flashing firmware

Subforum for general discussions. Do not dump your questions/problems here, but try to find the subforum where it belongs!
georgesattali
Posts: 102
Joined: Saturday 05 March 2016 17:40
Target OS: Raspberry Pi
Domoticz version:
Location: France
Contact:

SonOff without flashing firmware

Post by georgesattali » Saturday 22 July 2017 11:06

Hello,

It seems that someone has been able to hack sonoff without flashing them !

https://blog.ipsumdomus.com/sonoff-swit ... b2d6632c01

Did someone tried that ?

Bye,
GD

deofrem
Posts: 6
Joined: Sunday 17 September 2017 18:25
Target OS: -
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by deofrem » Sunday 17 September 2017 18:31

Please, can you explain me how do it after received

Code: Select all

As response you will get following JSON object

{
  "deviceid":"10000xxxxx",
  "apikey":"xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "accept":"post"
}

Lichtschilder
Posts: 10
Joined: Sunday 04 September 2016 9:43
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by Lichtschilder » Sunday 17 September 2017 20:36

you need to send a http-post to the sonoff containing the data described in the first link.

to get this working you'll need at least:
-a way to send http-post messages
-a webserver
-(self signed) certificates

This way of controlling sonoff might feel a lot more difficult than flashing the devices..
haven't tried myself and not sure if i will try this

georgesattali
Posts: 102
Joined: Saturday 05 March 2016 17:40
Target OS: Raspberry Pi
Domoticz version:
Location: France
Contact:

Re: SonOff without flashing firmware

Post by georgesattali » Sunday 17 September 2017 20:46

Sorry I cant tell you, I am still working on it myself.

to send http-post messages, you can use "curl"
you can take examples from https://stackoverflow.com/questions/717 ... pring-rest

the difficult point (for me) is the webserver, there, you need nodejs...

if I understand well (https://blog.ipsumdomus.com/sonoff-swit ... b2d6632c01), you don't need signed certificate.
WebSocket server should also be “secured” by bogus certificate. And this would be enough...
so I guess that false certificates (empty or text files) would be enough (also I think an ESP8266 cannot check crypted certificate).
the problem is that the code at ipsumdomus uses an unknown wlan package.

Regards,
GD

deofrem
Posts: 6
Joined: Sunday 17 September 2017 18:25
Target OS: -
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by deofrem » Monday 18 September 2017 8:50

After received JSON I wrote this in mypostfile.html :

Code: Select all

<html><head></head><body>
<form method="post" action="http://10.10.7.1/ap">
 <input type="text" name="version" value="4"/>
 <input type="text" name="ssid" value="MySSID"/>
 <input type="text" name="password" value="53161EF3C31531EF9CC31"/>
 <input type="text" name="serverName" value="http://191.163.4.130"/>
 <input type="text" name="port" value="8080"/><br>
<input type="submit" value="OK" />
</form></body></html>
after send form, nothing happend...Trying to do something but I do know what and I cannot explain what I see.
no attempt to connect to my wifi

I do not know how work websockets and nodejs.

PS : I have easyphp working fine on separate local network (no access internet). IP of server is 191.163.4.130:8080
Last edited by deofrem on Monday 18 September 2017 12:29, edited 1 time in total.

deofrem
Posts: 6
Joined: Sunday 17 September 2017 18:25
Target OS: -
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by deofrem » Monday 18 September 2017 9:07

georgesattali wrote:
Sunday 17 September 2017 20:46
Sorry I cant tell you, I am still working on it myself.
Unity is strength, to many we should get there
georgesattali wrote:
Sunday 17 September 2017 20:46
to send http-post messages, you can use "curl"
you can take examples from https://stackoverflow.com/questions/717 ... pring-rest
The form is Json ?

georgesattali wrote:
Sunday 17 September 2017 20:46
the difficult point (for me) is the webserver, there, you need nodejs...
Yes we need to install nodejs and understand how configure it.

georgesattali wrote:
Sunday 17 September 2017 20:46
if I understand well (https://blog.ipsumdomus.com/sonoff-swit ... b2d6632c01), you don't need signed certificate.

the problem is that the code at ipsumdomus uses an unknown wlan package.
I understand same.
Last edited by deofrem on Monday 18 September 2017 15:16, edited 1 time in total.

deofrem
Posts: 6
Joined: Sunday 17 September 2017 18:25
Target OS: -
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by deofrem » Monday 18 September 2017 10:53

After read this
https://darobin.github.io/formic/specs/json/
I try this and not works :

Code: Select all

<html><head></head><body>
<form enctype='application/json' method="post" action="http://10.10.7.1/ap">
 <input type="text" name="version" value="4"/>
 <input type="text" name="ssid" value="MySSID"/>
 <input type="text" name="password" value="53161EF3C31531EF9CC31"/>
 <input type="text" name="serverName" value="http://191.163.4.130"/>
 <input type="text" name="port" value="8080"/><br>
<input type="submit" value="OK" />
</form></body></html>
I read your link
https://stackoverflow.com/questions/717 ... pring-rest
but I do not understand where is the good way.
Can you give me your code please ?

from
https://systemoverlord.com/2016/08/24/p ... -form.html
I try also this :

Code: Select all

<html><head></head><body>
<form enctype='application/json' method="post" action="http://10.10.7.1/ap">
 <input type='text' name='{"version":4, "ssid":"MySSID", "password":"53161EF3C31531EF9CC31", "serverName":"http://191.163.4.130", "port": "8080" }' value='' /><br>
<input type="submit" value="OK" />
</form></body></html>
wih or without same text in value as name, with enctype='application/json' or enctype='text/plain', all possibilities with " or ' and I have nothing good.

deofrem
Posts: 6
Joined: Sunday 17 September 2017 18:25
Target OS: -
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by deofrem » Monday 18 September 2017 14:04

If I well understand after reading nodejs code at bottom page, I just need to install nodejs and create a file.js with code giving.
I open console and write nodejs file.js
With 2 errors I need also install nodejs-websocket and wlan with theese two commands npm install nodejs-websocket and npm install wlan
Last edited by deofrem on Sunday 24 September 2017 10:31, edited 1 time in total.

deofrem
Posts: 6
Joined: Sunday 17 September 2017 18:25
Target OS: -
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by deofrem » Monday 18 September 2017 15:18

georgesattali wrote:
Sunday 17 September 2017 20:46
the problem is that the code at ipsumdomus uses an unknown wlan package.
you are better and faster than me, because I just understand what you said about wlan package !

I am trying to write an other process...
Because it is object, I understand nothing, I will spend a lot of time !

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Seven days later I cannot write an other process, if I understand what I need to do, I am not enough strong to do it !

r3wt3d
Posts: 28
Joined: Friday 10 November 2017 5:09
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by r3wt3d » Friday 10 November 2017 5:12

That script is not working because he uses something "./wlan" which is not distributed.
In the comment I found this .. didn't tried it yet by myself though.

Check this out.

https://github.com/mdopp/simple-sonoff-server

I'm going to try it out by myself soon

r3wt3d
Posts: 28
Joined: Friday 10 November 2017 5:09
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by r3wt3d » Friday 10 November 2017 7:11

I don't have Domoticz installed currently but I tried this script.

1st. I have no clue about node.js
2nd. I have no clue about javascript
3rd. I have no clue about Domoticz
4th. I have no clue about pm2

I did something like this:

cd /var/lib/ #(or /usr/local or where ever you want it)
git clone https://github.com/mdopp/simple-sonoff-server.git
cd simple-sonoff-server
npm install # this will install all necessary modules it seems

vi sonoff.config.json
Edit the line you need:
"router" part is the WiFi Access Point information. "SSID" is your home SSID you want the SonOff to connect to.
"password" is the pre shared password for your Wifi network.

"server" part is where the dummy cloud server for SonOff is running. IP is normally a machine that runs sonoff.server.js like RaspberryPi.
httpPort: leave it as default value if it is not in use
httpsPort: leave it as default value if it is not in use
websocketPort: I changed to 1443 because 443 is normal https port and I already use it.

Once done save it.

This program has a server script and SonOff setup script.

starting the server:
you can just run with "node sonoff.server.js". However If you want it to run in background I recommend to use pm2.
if you don't have it installed yet install it with npm install pm2.
now run the sonoff.server.js with pm2:
pm2 start sonoff.server.js
pm2 startup (this will create a script to run the server at server bootup)

this will run sonoff.server in background.
you can use pm2 log sonoff.server to check the log, pm2 show sonoff.server to check the status etc.

Now setting up the device....I didn't do this now because I don't have any handy.
I will try this later today.

But as the document shows I should run the sonoff.setupdevice.js with "node sonoff.setupdevice.js" and
just turn the SonOff to registration mode by long pressing the black button on the device.

now I have been wondering how to check the device status etc.
Readme shows something like:
/devices => list off all devices that are currently known to the server.
/devices/:deviceId => shows the status of the device
/devices/:deviceId/on => turns the device "on"
/devices/:deviceId/off => turns the device "off" (typo in manual I think)

Soo...I tried
curl http://piserver:1080/devices
gives me [] back....I have no device so I don't know if this is correct but when I change the query to /devices/:123 then I get
Sonoff device :123 not found

Sweet :D

r3wt3d
Posts: 28
Joined: Friday 10 November 2017 5:09
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by r3wt3d » Friday 10 November 2017 13:21

Ok cool its working.

Code: Select all

root@pi:/var/lib/simple-sonoff-server# curl http://localhost:1081/devices
[{"id":"100002557a","state":"off","model":"ITA-GZ1-GL","version":"1.2.0"}
For pi users, I had to enable NetworkManager to get the setupdevice.js to work.
Install NetworkManager with apt-get install network-manager.
Comment out the iface wlan part of /etc/network/interfaces, change managed=true in /etc/NetworkManager/NetworkManager.conf
reboot
then
node sonoff.setupdevice.js
Long press the button on SonOff until it blinks fast.

Now I need to work on Domoticz side but I didn't even installed it yet...

r3wt3d
Posts: 28
Joined: Friday 10 November 2017 5:09
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by r3wt3d » Friday 10 November 2017 14:17

Quickly setup Domoticz and it works fine.
Added Dummy and added Switch with On command and Off command pointing to:

ON: http://127.0.0.1:1080/devices/deviceID/on
OFF: http://127.0.0.1:1080/devices/deviceID/off

Well that was easy...:D

It's not working with TH16 though.

ppoulla
Posts: 2
Joined: Monday 13 November 2017 11:04
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by ppoulla » Monday 13 November 2017 12:37

Dear r3wt3d,

First I would like to thank you for your job : your program offers great perspective for use sonoff without external server.
I tested it and I was pleased to pair and communicate with my sonoff switch from a raspberry pi board.

But I can't switch on my lamp. I wonder if it's a problem with the firmware version ( my version is 1.5.5 ).

I read http://blog.nanl.de/2017/05/sonota-flas ... -mechanism and I note some difference in the protocole used
for action update.

what do you think about ?

Thanks for all

r3wt3d
Posts: 28
Joined: Friday 10 November 2017 5:09
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by r3wt3d » Tuesday 14 November 2017 15:18

Hi ppoulla

which one you have? I can check. And you can turn it on manually and turn it off with script?
I updated all to latest official firmware and have no problem. I had problem adding device with version 2.0.1

btw I updated the original script to add support for TH10/16 with temperature/humidity.
I didn't commit it yet as I am still under testing but I would like to share this community.

I will post it later.

r3wt3d
Posts: 28
Joined: Friday 10 November 2017 5:09
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by r3wt3d » Tuesday 14 November 2017 15:36

Here is the script for adding support for temperature and humidity sensor.

I tested it with TH-10 and TH-16, with latest official firmware. I had problem registering the device with v2.0.1 (I think)
You have to place the relay near your device otherwise it seems to fail a lot to register. once registered it is possible
to move away from the device...I have no idea why.

sonoff.server.js
Spoiler: show

Code: Select all

var ws = require("nodejs-websocket");
const fs = require('fs');

//config for wlan
config = JSON.parse(fs.readFileSync('./sonoff.config.json'));

//set initialized parameters
var state = {
    knownDevices: []
};

// device in der liste finden
state.getDeviceById = (deviceId) => {
    return state.knownDevices.find(d => d.id == deviceId);
};

state.updateKnownDevice = (device) => {
    var updated = false;

    for (var i = 0; i < state.knownDevices.length; i++) {
        if (state.knownDevices[i].id == device.id) {
            state.knownDevices[i] = device;
            updated = true;
        }
    }
    if (!updated) {
        state.knownDevices.push(device);
    }
};

state.pushMessage = a => {
    var rq = {
        "apikey": "111111111-1111-1111-1111-111111111111",
        "action": a.action,
        "deviceid": a.target,
        "params": a.value,
        "userAgent": "app",
        "sequence": Date.now().toString(),
        "ts": 0,
        "from": "app"
    };
    var r = JSON.stringify(rq);
    console.log('REQ | WS | APP | ' + r);
    var device = state.getDeviceById(a.target);
    if (!device.messages) device.messages = [];
    device.messages.push(rq);
    device.conn.sendText(r);
};

// ----------- https server ------------------------
// Import libraries
var express = require('express');
var server = express();
var bodyParser = require('body-parser')
var https = require('https');
var http = require('http');

// Register body-parser
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({ extended: true }));

// Create https server & run
https.createServer({
    key: fs.readFileSync('./certs/66805011.key'),
    cert: fs.readFileSync('./certs/66805011.cert')
}, server).listen(config.server.httpsPort, function () {
    console.log('SONOFF API Server Started On Port %d', config.server.httpsPort);
});

// Create https server & run
http.createServer(server).listen(config.server.httpPort, function () {
    console.log('API Server Started On Port %d', config.server.httpPort);
});

// Register routes
server.post('/dispatch/device', function (req, res) {
    console.log('REQ | %s | %s ', req.method, req.url);
    console.log('REQ | %s', JSON.stringify(req.body));
    res.json({
        "error": 0,
        "reason": "ok",
        "IP": config.server.IP,
        "port": config.server.websocketPort
    });
});

//switch the device via postman (https) <= does not work from browser!!
server.get('/devices/:deviceId/:state', function (req, res) {
    console.log('GET | %s | %s ', req.method, req.url);
    var d = state.getDeviceById(req.params.deviceId);
    if (!d) {
        res.status(404).send('Sonoff device ' + req.params.deviceId + ' not found');
    } else {
        res.sendStatus(200);
        state.pushMessage({ action: 'update', value: { switch: req.params.state }, target: d.id });
    }
});

//get status of known devices via postman (https) <= does not work from browser!!
server.get('/devices/:deviceId', function (req, res) {
    console.log('GET | %s | %s ', req.method, req.url);
    var d = state.getDeviceById(req.params.deviceId);
    if (!d) {
        res.status(404).send('Sonoff device ' + req.params.deviceId + ' not found');
    } else {
        res.json({ id: d.id, state: d.state, temp: d.temp, hum: d.hum, model: d.model, kind: d.kind, version: d.version } );
    }
});

//get a list of known devices via postman (https) <= does not work from browser!!
server.get('/devices', function (req, res) {
    console.log('GET | %s | %s ', req.method, req.url);
    res.json(state.knownDevices.map(x => { return { id: x.id, state: x.state, model: x.model, kind: x.kind, version: x.version } }));
});
// ----------- https server ------------------------

// setup a server, that will respond to the SONOFF requests
// this is the replacement for the SONOFF cloud!
var wsOptions = {
    secure: true,
    key: fs.readFileSync('./certs/66805011.key'),
    cert: fs.readFileSync('./certs/66805011.cert'),
};

ws.createServer(wsOptions, function (conn) {
    console.log("WS | Server is up %s:%s to %s:%s", config.server.IP, config.server.websocketPort, conn.socket.remoteAddress, conn.socket.remotePort);
    conn.on("text", function (str) {
        var data = JSON.parse(str);
        console.log('REQ | WS | DEV | %s', JSON.stringify(data));
        res = {
            "error": 0,
            "deviceid": data.deviceid,
            "apikey": "111111111-1111-1111-1111-111111111111"
        };
        if (data.action) {
            switch (data.action) {
                case 'date':
                    res.date = new Date().toISOString();
                    break;
                case 'query':
                    //device wants information
                    var device = state.getDeviceById(data.deviceid);
                    if (!device) {
                        console.log('ERR | WS | Unknown device ', data.deviceid);
                    } else {
                        /*if(data.params.includes('timers')){
                         console.log('INFO | WS | Device %s asks for timers',device.id);
                         if(device.timers){
                          res.params = [{timers : device.timers}];
                         }
                        }*/
                        res.params = {};
                        data.params.forEach(p => {
                            res.params[p] = device[p];
                        });
                    }
                    break;
                case 'update':
                    //device wants to update its state
                    var device = state.getDeviceById(data.deviceid);
                    if (!device) {
                        console.log('ERR | WS | Unknown device ', data.deviceid);
                    } else {
			if (data.params.switch) {
                        	device.state = data.params.switch;
				}
			if (data.params.currentTemperature) {
				device.temp = data.params.currentTemperature;
				}
			if (data.params.currentHumidity) {
				device.hum = data.params.currentHumidity;
				}
                        device.conn = conn;
                        state.updateKnownDevice(device);
                    }

                    break;
                case 'register':
                    var device = {
                        id: data.deviceid
                    };

                    //this is not valid anymore?! type is not based on the first two chars
                    var type = data.deviceid.substr(0, 2);
                    if (type == '01') device.kind = 'switch';
                    else if (type == '02') device.kind = 'light';
                    else if (type == '03') device.kind = 'sensor'; //temperature and humidity. No timers here;

                    device.version = data.romVersion;
                    device.model = data.model;
                    device.conn = conn;
                    state.updateKnownDevice(device);
                    console.log('INFO | WS | Device %s registered', device.id);
                    break;
                default: console.log('TODO | Unknown action "%s"', data.action); break;
            }
        } else {
            if (data.sequence && data.deviceid) {
                var device = state.getDeviceById(data.deviceid);
                if (!device) {
                    console.log('ERR | WS | Unknown device ', data.deviceid);
                } else {
                    if (device.messages) {
                        var message = device.messages.find(item => item.sequence == data.sequence);
                        if (message) {
                            device.messages = device.messages.filter(function(item) {
                                return item !== message;
                            })
                            device.state = message.params.switch;
                            state.updateKnownDevice(device);
                            console.log('INFO | WS | APP | action has been accnowlaged by the device ' + JSON.stringify(data));
                        } else {
                            console.log('ERR | WS | No message send, but received an anser', JSON.stringify(data));
                        }
                    } else {
                        console.log('ERR | WS | No message send, but received an anser', JSON.stringify(data));
                    }
            }
            } else {
                console.log('TODO | WS | Not data action frame\n' + JSON.stringify(data));
            }
        }
        var r = JSON.stringify(res);
        console.log('RES | WS | DEV | ' + r);
        conn.sendText(r);
    });
    conn.on("close", function (code, reason) {
        console.log("Connection closed");
    });
}).listen(config.server.websocketPort, config.server.IP);
additionally here is a dirty update script for temperature/humidity. You need to install "jq", install it with apt-get.
Add virtual "Temp + Humidity" sensor device in domoticz.

update_temp_hum.sh
Spoiler: show

Code: Select all

#!/bin/bash
#change below 
URL="http://localhost:8080"
USER="username" #for domoticz authentication
PASS="password" #for domoticz authentication
ID="3" # replace with IDx of your temperature virtual device in domoticz
DEVICE="10000xxxxx" #put your SonOff ID here

TEMPERATURE="/json.htm?type=command&param=udevice&idx=$ID&nvalue=0&svalue="
#Change :1081 to SonOff HTTP Server port on your local host.
value=`curl -s "http://localhost:1081/devices/$DEVICE" | jq -r '"\(.temp);\(.hum)"'` ;

# remove '>>/dev/null' to see the status result
# remove '--user $USER:$PASS' if you do not have any user authentication.
echo `curl -s --user $USER:$PASS $URL$TEMPERATURE$value\;0` | jq -r '"\(.status)"' >> /dev/null

add this to crontab like this:
*/1 * * * * /var/lib/simple-sonoff-server/update_temp_hum.sh
this will update temperature every minute.

ppoulla
Posts: 2
Joined: Monday 13 November 2017 11:04
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by ppoulla » Tuesday 14 November 2017 18:10

Hi r3wt3d,

Thanks for your answer ! I have no more problem with my Sonoff Basic WiFi Wireless Switch (firmware version 1.5.5) !

I believed the script needs the api key of the switch so I have replaced the api key 111111111-1111-1111-1111-111111111111 with the internal api key.

I wrote back to api key 111111111-1111-1111-1111-111111111111 and the script works well.

r3wt3d
Posts: 28
Joined: Friday 10 November 2017 5:09
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by r3wt3d » Wednesday 15 November 2017 12:21

good to hear you can use it now. But no, the API key is used to communicate with the official coolkit(eWelink) cloud server for validation and is not used in this script because this script doesn't check for valid keys. :)

maximus
Posts: 12
Joined: Wednesday 15 November 2017 23:40
Target OS: -
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by maximus » Wednesday 15 November 2017 23:55

hi im running the simple sonoff server too.

i have a double light switch like sonoff touch with 2 switches

in the console.log there are new lines when i turned on and of the light manually

{"switches":[{"switch":off","outlet":0},{"switch":off","outlet":1},{"switch":off","outlet":2},{"switch":off","outlet":3},"fwVersion":"2.0.1",rssi":-49}}

{"switches":[{"switch":on","outlet":0},{"switch":on","outlet":1},{"switch":off","outlet":2},{"switch":off","outlet":3},"fwVersion":"2.0.1",rssi":-49}}

{"switches":[{"switch":off","outlet":0},{"switch":on","outlet":1},{"switch":off","outlet":2},{"switch":off","outlet":3},"fwVersion":"2.0.1",rssi":-49}}

{"switches":[{"switch":of","outlet":0},{"switch":off","outlet":1},{"switch":off","outlet":2},{"switch":off","outlet":3},"fwVersion":"2.0.1",rssi":-49}}

how can i submit the outlet params?

if i try this:

http://127.0.0.1:1081/devices/deviceid/off

it only says ok, but the light is still shining

r3wt3d
Posts: 28
Joined: Friday 10 November 2017 5:09
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: SonOff without flashing firmware

Post by r3wt3d » Thursday 16 November 2017 7:20

Hi Maximus

maybe modifying the server will do the job but I can't test by myself...

Code: Select all

server.get('/devices/:deviceId/:state', function (req, res) {
    console.log('GET | %s | %s ', req.method, req.url);
    var d = state.getDeviceById(req.params.deviceId);
    if (!d) {        res.status(404).send('Sonoff device ' + req.params.deviceId + ' not found');
    } else {
        res.sendStatus(200);
       state.pushMessage({ action: 'update', value: { switch: req.params.state }, target: d.id });
    }                     
change this pushMessage part to something like
state.pushMessage({ action: 'update', value: { switch: req.params.state , outlet: 0 }, target: d.id });
and check if it turns on/off the outlet 0.

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests