soma-ctrl
v2.0.1
Published
Control Soma BTLE Smart Shade devices by HTTP or MQTT
Downloads
25
Maintainers
Readme
SOMA Blind Controller Util
Util for controlling SOMA smart shade, either over MQTT or via a HTTP API
Requirements
- SOMA smart shade device that has been configured with the SOMA app
- Bluetooth 4.0 LE hardware
- OS supported by noble (I've only tested on macOS and Raspbian)
- Node 8.16.1 or higher (Tested on Node 12.10.0, 11.15.0, 10.15.2, 9.11.2, 8.16.1)
- (Potentially a Bluetooth stick to itself, if you're using some other Bluetooth software, see #59)
Installation
Run npm install -g soma-ctrl
Usage
somactrl
by itself will print usage information
By default, device scanning will be active for 30 seconds, and any supported ones will be connected to. You may optionally:
- Alter the device scanning timeout, e.g. scan for 60 seconds:
somactrl -t 60
- Specify the number of devices you expect to connect to, e.g. 4 devices expected:
somactrl -e 4
- Manually specify a list of device IDs to connect to, e.g. connect to RISE108 and RISE117:
somactrl RISE108 RISE117
- Manually specify a list of MAC addresses to connect to, e.g.:
somactrl f5:11:7b:ee:f3:43
You must then specify options to use either MQTT, HTTP or both
To use with HTTP
Specify a port for the API to listen on with -l
:
somactrl -l 3000
To use with MQTT
Specify a broker URL with --url
option:
somactrl --url mqtt://yourbroker
(mqtt/mqtts/ws/wss accepted)
Username and password for MQTT may be specified with -u
and -p
option
If no password argument is supplied, you can enter it interactively
Base topic defaults to homeassistant
, but may be configured with the -topic
option
MQTT
For each device connected, data will be published to the following topics:
<baseTopic>/cover/<deviceID>/position
- position
<baseTopic>/cover/<deviceID>/connected
- connected
or disconnected
<baseTopic>/cover/<deviceID>/battery
- battery level
To issue commands:
Move: <baseTopic>/cover/<deviceID>/move
- message: int position between 0 (closed) and 100 (open)
Stop: <baseTopic>/cover/<deviceID>/move
- message: 'stop'
Identify (beep device): <baseTopic>/cover/<deviceID/identify
- message is ignored
In addition, for use with Home Assistant MQTT Discovery:
To automatically setup the cover device:
<baseTopic>/cover/<deviceID>/config
will be set to, e.g.:
{
"name": "Living Room1",
"availability_topic": "homeassistant/cover/RISE148/connection",
"payload_available": "connected",
"payload_not_available": "disconnected",
"position_topic": "homeassistant/cover/RISE148/position",
"set_position_topic": "homeassistant/cover/RISE148/move",
"command_topic": "homeassistant/cover/RISE148/move",
"payload_open": 100,
"payload_close": 0,
"unique_id": "soma_RISE148_cover",
"device": {
"identifiers": "soma_RISE148",
"name": "RISE148",
"manufacturer": "Soma",
"model": "Smart Shade"
}
}
To automatically setup a battery sensor:
<baseTopic>/sensor/cover_<deviceName|slugified>_battery/config
will be set to, e.g.:
{
"name": "Cover <deviceID> battery",
"state_topic": "<baseTopic>/cover/<deviceID>/battery",
"unit_of_measurement": "%",
"device_class": "battery",
"unique_id": "soma_<deviceID>_battery",
"device": {
"identifiers": "soma_RISE148",
"name": "RISE148",
"manufacturer": "Soma",
"model": "Smart Shade"
}
}
Parameters
<deviceID>
has format RISEnnn
or the device's MAC address in lowercase, with the colon's stripped out and cannot be changed
<deviceName|slugified>
will be the device name (as configured in the app) with spaces replaced by underscores
HTTP Endpoints
GET /
: list devices.
Response type: [String : Device]
- ID as String key, Device as value
{
"RISE148": {
"id": "RISE148",
"battery": 29,
"batteryLevelLastChanged": "2018-05-03T17:14:10.590Z",
"position": 0,
"positionLastChanged": "2018-05-03T17:14:10.320Z",
"connectionState": "connected",
"state": "closed",
"group": "Living Room",
"name": "Living Room1"
},
"RISE236": {
"id": "RISE236",
"battery": 28,
"batteryLevelLastChanged": "2018-05-03T17:14:10.497Z",
"position": 0,
"positionLastChanged": "2018-05-03T17:14:10.198Z",
"connectionState": "connected",
"state": "closed",
"group": "Living Room",
"name": "Living Room2"
}
}
GET /<deviceID>
: Get individual device data (or 404 if no device by that ID).
Response type: Device
example:
{
"id": "RISE148",
"battery": 29,
"batteryLevelLastChanged": "2018-05-03T17:14:10.590Z",
"position": 0,
"positionLastChanged": "2018-05-03T17:14:10.320Z",
"connectionState": "connected",
"state": "closed",
"group": "Living Room",
"name": "Living Room1"
}
POST /<deviceID>/identify
: Ask deviceID to identify itself (beep). Response type: 200 - OK
or 404 - Not Found
POST /<deviceID>/move?position=<position>
: Ask deviceID to move to <position>
. Response type: Device
or 404
POST /<deviceID>/stop
: Ask deviceID to stop moving. Response type: 200 - OK
or 404 - Not Found
POST /<deviceID>/calibrateModeStart
: Enable calibrate mode on deviceID. Response type: 200 - OK
or 404 - Not Found
POST /<deviceID>/moveUp
: Request device to move up. Beware that if calibration mode is enabled, the defined top position is not honoured. Response type: 200 - OK
or 404 - Not Found
POST /<deviceID>/stop
: Request device to stop moving. Response type: 200 - OK
or 404 - Not Found
POST /<deviceID>/moveDown
: Request device to move down. Beware that if calibration mode is enabled, the defined bottom position is not honoured. Response type: 200 - OK
or 404 - Not Found
POST /<deviceID>/calibrateTop
: When in calibrate mode, set the current position as the top-most position. Response Type: 200 - OK
or 404 - Not Found
POST /<deviceID>/calibrateBottom
: When in calibrate mode, set the current position as the bottom-most position. Response Type: 200 - OK
or 404 - Not Found
POST /<deviceID>/calibrateModeStop
: Disable calibrate mode on deviceID. Response type; 200 - OK
or 404 - Not Found
POST /exit
: Quit somactrl (useful if you run with systemd and want to restart). Response type: 200 - OK
Parameters
<deviceID>
has format RISEnnn
or the device's MAC address in lowercase, with the colon's stripped out and cannot be changed
<position>
should be an integer between 0 (closed) and 100 (open)