homieiot / homie-esp8266

💡 ESP8266 framework for Homie, a lightweight MQTT convention for the IoT
http://homieiot.github.io/homie-esp8266
MIT License
1.36k stars 308 forks source link

change configuration in normal mode #36

Closed CWempe closed 8 years ago

CWempe commented 8 years ago

It would be nice to change some/all parameters via mqtt in normal mode.

This should be easy for $name, $fwname and $fwversion.

Maybe this would even be possible for wifi (ssid, passphrase, ip, ..) and mqtt settings. Yes, one could argue that this is dangerous, because the device might become unreachable in case the new configuration is incorrect.

marvinroger commented 8 years ago

Firmware names/versions are part of the running sketch, so this is not something you're supposed to change. For the name, why not. And for network settings, this would require a lot of overhead in RAM / network time, as we would need to either spawn a HTTP server in normal mode, or subscribe to new topics to change the config. I don't like this approach.

A solution would be to allow the config.json to be changed via OTA. But for the time being, you can simply reset the device and send the new credentials. This is tedious, but you're not supposed to change your network regurarly.

jpmens commented 8 years ago

Would allowing config.json to be changed via an MQTT publish be a solution? This could be followed by a $reset or something to make it active.

mosquitto_pub -t 'devices/0d88a0e0/$config' -f config.json
marvinroger commented 8 years ago

Yes and no. The sample config.json in the wiki is 447 bytes and the max packet size of PubSubClient (the underlying MQTT library) is 128 bytes, including header. This means people would have to change this value in the PubSubClient .h file, this is not appropriate. There is a discussion about adding a programmatic way to change this max packet size : https://github.com/knolleary/pubsubclient/issues/110.

rigorm commented 8 years ago

I have a idea, would it be possible to have another file created on the SPFIF and then , device restarted and if that new file exist, the delete the old one, rename the new one and continue booting ?

How to give new info is still to be determined.

marvinroger commented 8 years ago

Yes it would, but there is no need to, we could simply rewrite the current configuration file, and it would be taken into account at next reboot.

So yes, the question is how to actually get the new information.

rigorm commented 8 years ago

ok then, how about doing the same as OTA.. atvertise a config version and have a URL to upload the new version (I don't know how exactly OTA does it). Could be the way to go perhaps ?

marvinroger commented 8 years ago

This is the last feature that needs to be designed before we release v2.0.0.

Now that there is no limitation on the payload size in the MQTT library, I guess @jpmens's idea is the most straightforward one: just publish the new config.json to devices/0d88a0e0/$config/set. I am pretty sure people will also request to have access to the config.json remotely. Then what about exposing the config.json in a retained devices/0d88a0e0/$config? The only problem I see is that the config.json contains both the Wi-Fi and MQTT credentials. But if you have access to the MQTT broker, it means you actually have access to the Wi-Fi and MQTT, so you know the credentials anyway.

What do you think?

jpmens commented 8 years ago

Publishing the config to $config retained sounds like a good idea to me (and we could easily add viewing that to, say, homie-ota, which would be very good). What I would definitely do though is to omit the credentials from the configuration to ensure they're not lying around, so to speak. While I agree that this doesn't really matter within a closed environment, it's bad practice, so we should avoid credentials being stored outside of the device.

marvinroger commented 8 years ago

I agree, so given the following config.json:

{
  "name": "The kitchen light",
  "device_id": "kitchen-light",
  "wifi": {
    "ssid": "Network_1",
    "password": "I'm a Wi-Fi password!"
  },
  "mqtt": {
    "host": "192.168.1.10",
    "port": 1883,
    "base_topic": "devices/",
    "auth": true,
    "username": "user",
    "password": "pass"
  },
  "ota": {
    "enabled": true
  }
}

We would strip wifi.password, mqtt.username and mqtt.password. Or maybe let the mqtt.username?

flaviostutz commented 8 years ago

Great! In my case I would have an OAUTH2 token as mqtt password and even refresh it remotely from time to time to increase security.

I few weeks ago I was wondering about having a pub/private key schema so that I could encrypt/sign data that is stored on mqtt. The key pair would be generated at the device configuration and the private key would never go off the device to avoid disclosure. This way I could be sure about data origin (through device signatures) and crypt secret data (ex.: passwords, sensitive sensor data).

The "problem" about security (regarding to "config.json") over mqtt depends on the case. For simple, single user projects, there is no harm putting your wifi password as plain text in a private mqtt, but for greater projects that is bad. As more people uses it, more people will try to break it.

+1

Thanks and continue your pursuit for smart simplicity!

Flávio Stutz

Sent from my iPhone

On Jun 26, 2016, at 11:53, Marvin Roger notifications@github.com wrote:

This is the last feature that needs to be designed before we release v2.0.0.

Now that there is no limitation on the payload size in the MQTT library, I guess @jpmens's idea is the most straightforward one: just publish the new config.json to devices/0d88a0e0/$config/set. I am pretty sure people will also request to have access to the config.json remotely. Then what about exposing the config.json in a retained devices/0d88a0e0/$config? The only problem I see is that the config.json contains both the Wi-Fi and MQTT credentials. But if you have access to the MQTT broker, it means you actually have access to the Wi-Fi and MQTT, so you know the credentials anyway.

What do you think?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

jpmens commented 8 years ago

@marvinroger I think all three should be stripped, so wifi.password, mqtt.username and mqtt.password

marvinroger commented 8 years ago

Let's strip these tree fields then.

@flaviostutz be careful, asymmetric cryptography is way slower than symmetric cryptography. You'd better use public-key crypto only to exchange a symmetric key. Take a look at https://github.com/kaeferfreund/ChaChaPoly_ESP8266 , a recent cipher-suite prety well suited for embedded devices.

jamesmyatt commented 8 years ago

Would it be worth making it so that you can publish a partial configuration to $config\set? So that, to change the name, you could just publish {"name": "new-name"}, or to disable the OTA, it would be {"ota": {"enabled": false}}.

marvinroger commented 8 years ago

@Nzbuu totally, and this is needed, as as said above, the credentials will be stripped, so the JSON cannot be a full config.json anyway.

marvinroger commented 8 years ago

Yay! :tada:

The current configuration is published to <basetopic>/<deviceid>/$implementation/config, with wifi.password, mqtt.username and mqtt.password stripped. To change the configuration, send your incremental changes to <basetopic>/<deviceid>/$implementation/config/set. If the new configuration is correct, the device will reboot with the new configuration!

Coming in v2.