├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── nodejs.yml ├── package.json ├── LICENSE ├── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.log 3 | .npmignore 4 | .jshintrc 5 | .idea 6 | **/*.iml 7 | .DS_Store -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Additional context** 14 | Add any other context about the feature request here. 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **Expected behavior** 11 | A clear and concise description of what you expected to happen. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. ... 16 | 2. ... 17 | 3. ... 18 | 19 | **Version** (output of `npm list -g homebridge homebridge-http-temperature-sensor`) 20 | - homebridge: 21 | - homebridge-http-temperature-sensor: 22 | 23 | **Configuration** 24 | ```json 25 | Your configuration goes in here 26 | ``` 27 | 28 | **Additional context** 29 | Add any other context about the problem here. 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "homebridge-http-temperature-sensor", 3 | "version": "1.0.10", 4 | "description": "Http temperature sensor for Homebridge", 5 | "license": "ISC", 6 | "keywords": [ 7 | "homebridge-plugin" 8 | ], 9 | "scripts": { 10 | "test": "echo no test specified" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/Supereg/homebridge-http-temperature-sensor" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/Supereg/homebridge-http-temperature-sensor/issues" 18 | }, 19 | "engines": { 20 | "node": ">=10.17.0", 21 | "homebridge": ">=0.4.0" 22 | }, 23 | "dependencies": { 24 | "homebridge-http-base": "~2.1.12" 25 | }, 26 | "devDependencies": { 27 | "homebridge": "^1.3.5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License (ISC) 2 | Copyright (c) 2017-2019, Andreas Bauer 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 | PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Node-CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | node-version: [10.x, 12.x, 13.x] 13 | 14 | steps: 15 | - uses: actions/checkout@v1 16 | - name: Use Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - name: npm install 21 | run: npm ci 22 | env: 23 | CI: true 24 | - name: npm build 25 | run: npm run build --if-present 26 | env: 27 | CI: true 28 | - name: npm test 29 | run: npm test 30 | env: 31 | CI: true 32 | 33 | publish-npm: 34 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') 35 | 36 | needs: build 37 | 38 | runs-on: ubuntu-latest 39 | 40 | steps: 41 | - uses: actions/checkout@v1 42 | - uses: actions/setup-node@v1 43 | with: 44 | node-version: 10 45 | registry-url: https://registry.npmjs.org/ 46 | - run: npm ci 47 | - run: npm publish 48 | env: 49 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 50 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | let Service, Characteristic, api; 4 | 5 | const _http_base = require("homebridge-http-base"); 6 | const http = _http_base.http; 7 | const configParser = _http_base.configParser; 8 | const PullTimer = _http_base.PullTimer; 9 | const notifications = _http_base.notifications; 10 | const MQTTClient = _http_base.MQTTClient; 11 | const Cache = _http_base.Cache; 12 | const utils = _http_base.utils; 13 | 14 | const packageJSON = require("./package.json"); 15 | 16 | module.exports = function (homebridge) { 17 | Service = homebridge.hap.Service; 18 | Characteristic = homebridge.hap.Characteristic; 19 | 20 | api = homebridge; 21 | 22 | homebridge.registerAccessory("homebridge-http-temperature-sensor", "HTTP-TEMPERATURE", HTTP_TEMPERATURE); 23 | }; 24 | 25 | const TemperatureUnit = Object.freeze({ 26 | Celsius: "celsius", 27 | Fahrenheit: "fahrenheit" 28 | }); 29 | 30 | function HTTP_TEMPERATURE(log, config) { 31 | this.log = log; 32 | this.name = config.name; 33 | this.debug = config.debug || false; 34 | 35 | if (config.getUrl) { 36 | try { 37 | this.getUrl = configParser.parseUrlProperty(config.getUrl); 38 | } catch (error) { 39 | this.log.warn("Error occurred while parsing 'getUrl': " + error.message); 40 | this.log.warn("Aborting..."); 41 | return; 42 | } 43 | } 44 | else { 45 | this.log.warn("Property 'getUrl' is required!"); 46 | this.log.warn("Aborting..."); 47 | return; 48 | } 49 | 50 | this.unit = utils.enumValueOf(TemperatureUnit, config.unit, TemperatureUnit.Celsius); 51 | if (!this.unit) { 52 | this.unit = TemperatureUnit.Celsius; 53 | this.log.warn(`${config.unit} is an unsupported temperature unit! Using default!`); 54 | } 55 | 56 | this.statusCache = new Cache(config.statusCache, 0); 57 | this.statusPattern = /(-?[0-9]{1,3}(\.[0-9])?)/; 58 | try { 59 | if (config.statusPattern) 60 | this.statusPattern = configParser.parsePattern(config.statusPattern); 61 | } catch (error) { 62 | this.log.warn("Property 'statusPattern' was given in an unsupported type. Using default one!"); 63 | } 64 | this.patternGroupToExtract = 1; 65 | if (config.patternGroupToExtract) { 66 | if (typeof config.patternGroupToExtract === "number") 67 | this.patternGroupToExtract = config.patternGroupToExtract; 68 | else 69 | this.log.warn("Property 'patternGroupToExtract' must be a number! Using default value!"); 70 | } 71 | 72 | this.homebridgeService = new Service.TemperatureSensor(this.name); 73 | this.homebridgeService.getCharacteristic(Characteristic.CurrentTemperature) 74 | .setProps({ 75 | minValue: -100, 76 | maxValue: 100 77 | }) 78 | .on("get", this.getTemperature.bind(this)); 79 | 80 | /** @namespace config.pullInterval */ 81 | if (config.pullInterval) { 82 | this.pullTimer = new PullTimer(log, config.pullInterval, this.getTemperature.bind(this), value => { 83 | this.homebridgeService.setCharacteristic(Characteristic.CurrentTemperature, value); 84 | }); 85 | this.pullTimer.start(); 86 | } 87 | 88 | /** @namespace config.notificationPassword */ 89 | /** @namespace config.notificationID */ 90 | notifications.enqueueNotificationRegistrationIfDefined(api, log, config.notificationID, config.notificationPassword, this.handleNotification.bind(this)); 91 | 92 | /** @namespace config.mqtt */ 93 | if (config.mqtt) { 94 | let options; 95 | try { 96 | options = configParser.parseMQTTOptions(config.mqtt); 97 | } catch (error) { 98 | this.log.error("Error occurred while parsing MQTT property: " + error.message); 99 | this.log.error("MQTT will not be enabled!"); 100 | } 101 | 102 | if (options) { 103 | try { 104 | this.mqttClient = new MQTTClient(this.homebridgeService, options, this.log); 105 | this.mqttClient.connect(); 106 | } catch (error) { 107 | this.log.error("Error occurred creating MQTT client: " + error.message); 108 | } 109 | } 110 | } 111 | } 112 | 113 | HTTP_TEMPERATURE.prototype = { 114 | 115 | identify: function (callback) { 116 | this.log("Identify requested!"); 117 | callback(); 118 | }, 119 | 120 | getServices: function () { 121 | if (!this.homebridgeService) 122 | return []; 123 | 124 | const informationService = new Service.AccessoryInformation(); 125 | 126 | informationService 127 | .setCharacteristic(Characteristic.Manufacturer, "Andreas Bauer") 128 | .setCharacteristic(Characteristic.Model, "HTTP Temperature Sensor") 129 | .setCharacteristic(Characteristic.SerialNumber, "TS01") 130 | .setCharacteristic(Characteristic.FirmwareRevision, packageJSON.version); 131 | 132 | return [informationService, this.homebridgeService]; 133 | }, 134 | 135 | handleNotification: function(body) { 136 | const characteristic = utils.getCharacteristic(this.homebridgeService, body.characteristic); 137 | if (!characteristic) { 138 | this.log("Encountered unknown characteristic when handling notification (or characteristic which wasn't added to the service): " + body.characteristic); 139 | return; 140 | } 141 | 142 | let value = body.value; 143 | if (body.characteristic === "CurrentTemperature" && this.unit === TemperatureUnit.Fahrenheit) 144 | value = (value - 32) / 1.8; 145 | 146 | if (this.debug) 147 | this.log("Updating '" + body.characteristic + "' to new value: " + body.value); 148 | characteristic.updateValue(value); 149 | }, 150 | 151 | getTemperature: function (callback) { 152 | if (!this.statusCache.shouldQuery()) { 153 | const value = this.homebridgeService.getCharacteristic(Characteristic.CurrentTemperature).value; 154 | if (this.debug) 155 | this.log(`getTemperature() returning cached value ${value}${this.statusCache.isInfinite()? " (infinite cache)": ""}`); 156 | 157 | callback(null, value); 158 | return; 159 | } 160 | 161 | http.httpRequest(this.getUrl, (error, response, body) => { 162 | if (this.pullTimer) 163 | this.pullTimer.resetTimer(); 164 | 165 | if (error) { 166 | this.log("getTemperature() failed: %s", error.message); 167 | callback(error); 168 | } 169 | else if (!http.isHttpSuccessCode(response.statusCode)) { 170 | this.log("getTemperature() returned http error: %s", response.statusCode); 171 | callback(new Error("Got http error code " + response.statusCode)); 172 | } 173 | else { 174 | let temperature; 175 | try { 176 | temperature = utils.extractValueFromPattern(this.statusPattern, body, this.patternGroupToExtract); 177 | } catch (error) { 178 | this.log("getTemperature() error occurred while extracting temperature from body: " + error.message); 179 | callback(new Error("pattern error")); 180 | return; 181 | } 182 | 183 | if (this.unit === TemperatureUnit.Fahrenheit) 184 | temperature = (temperature - 32) / 1.8; 185 | 186 | if (this.debug) 187 | this.log("Temperature is currently at %s", temperature); 188 | 189 | this.statusCache.queried(); 190 | callback(null, temperature); 191 | } 192 | }); 193 | }, 194 | 195 | }; 196 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # homebridge-http-temperature-sensor Plugin 2 | 3 | This [Homebridge](https://github.com/nfarina/homebridge) plugin can be used integrate your temperature sensor which has a 4 | http api into HomeKit. 5 | 6 | ## Installation 7 | 8 | First of all you need to have [Homebridge](https://github.com/nfarina/homebridge) installed. Refer to the repo for 9 | instructions. 10 | Then run the following command to install `homebridge-http-temperature-sensor` 11 | 12 | ``` 13 | sudo npm install -g homebridge-http-temperature-sensor 14 | ``` 15 | 16 | ## Updating the temperature in HomeKit 17 | 18 | The _'CurrentTemperature'_ characteristic has the permission to `notify` the HomeKit controller of state 19 | changes. `homebridge-http-temperature-sensor` supports two concepts to send temperature changes to HomeKit. 20 | 21 | ### The 'pull' way: 22 | 23 | The 'pull' way is probably the easiest to set up and supported in every scenario. `homebridge-http-temperature-sensor` 24 | requests the temperature of the sensor in an specified interval (pulling) and sends the value to HomeKit. 25 | Look for `pullInterval` in the list of configuration options if you want to configure it. 26 | 27 | ### The 'push' way: 28 | 29 | When using the 'push' concept, the http device itself sends the updated value to `homebridge-http-temperature-sensor` 30 | whenever values change. This is more efficient as the new value is updated instantly and 31 | `homebridge-http-temperature-sensor` does not need to make needless requests when the value didn't actually change. 32 | However because the http device needs to actively notify the `homebridge-http-temperature-sensor` there is more 33 | work needed to implement this method into your http device. 34 | 35 | #### Using MQTT: 36 | 37 | MQTT (Message Queuing Telemetry Transport) is a protocol widely used by IoT devices. IoT devices can publish messages 38 | on a certain topic to the MQTT broker which then sends this message to all clients subscribed to the specified topic. 39 | In order to use MQTT you need to setup a broker server ([mosquitto](https://github.com/eclipse/mosquitto) is a solid 40 | open source MQTT broker running perfectly on a device like the Raspberry Pi) and then instruct all clients to 41 | publish/subscribe to it. 42 | 43 | #### Using 'homebridge-http-notification-server': 44 | 45 | For those of you who are developing the http device by themselves I developed a pretty simple 'protocol' based on http 46 | to send push-updates. 47 | How to implement the protocol into your http device can be read in the chapter 48 | [**Notification Server**](#notification-server) 49 | 50 | 51 | ## Configuration 52 | 53 | The configuration can contain the following properties: 54 | 55 | ##### Basic configuration options: 56 | 57 | * `accessory` \ **required**: Defines the plugin used and must be set to **"HTTP-TEMPERATURE"** for this plugin. 58 | * `name` \ **required**: Defines the name which is later displayed in HomeKit 59 | * `getUrl` \ **required**: Defines the url (and other properties when using 60 | and urlObject) to query the current temperature (in celsius) from the sensor. By default it expects the http server 61 | to return the temperature as a float ranging from 0-100 (step 0.1). 62 | * `unit` \ **optional** \(Default: **"celsius**\): Defines unit expected from the http server. The following 63 | are available: 64 | * **"celsius"**: Using celsius to calculate temperature 65 | * **"fahrenheit"**: Using fahrenheit to calculate temperature 66 | 67 | ##### Advanced configuration options: 68 | 69 | * `statusPattern` \ **optional** \(Default: **"(-?[0-9]{1,3}(\.[0-9]))"**): Defines a regex pattern with which the 70 | temperature is extracted from the body of the http response from the `getUrl`. The group which should 71 | be extracted can be configured with the `patternGroupToExtract` property. 72 | [More about regex pattern](https://www.w3schools.com/jsref/jsref_obj_regexp.asp). 73 | * `patternGroupToExtract` \ **optional** \(Default: **1**\): Defines the regex group of which the temperature 74 | is extracted. 75 | * `statusCache` \ **optional** \(Default: **0**\): Defines the amount of time in milliseconds a queried value 76 | of the _CurrentTemperature_ characteristic is cached before a new request is made to the http device. 77 | Default is **0** which indicates no caching. A value of **-1** will indicate infinite caching. 78 | 79 | - `pullInterval` \ **optional**: The property expects an interval in **milliseconds** in which the plugin 80 | pulls updates from your http device. For more information read [pulling updates](#the-pull-way). 81 | 82 | * `mqtt` \<[mqttObject](#mqttobject)\> **optional**: Defines all properties used for mqtt connection ([More on MQTT](#using-mqtt)). 83 | For configuration see [mqttObject](#mqttobject). 84 | 85 | - `debug` \ **optional**: Enable debug mode and write more logs. 86 | 87 | Below are two example configurations. One is using a simple string url and the other is using a simple urlObject. 88 | Both configs can be used for a basic plugin configuration. 89 | ```json 90 | { 91 | "accessories": [ 92 | { 93 | "accessory": "HTTP-TEMPERATURE", 94 | "name": "Temperature Sensor", 95 | 96 | "getUrl": "http://localhost/api/getTemperature" 97 | } 98 | ] 99 | } 100 | ``` 101 | ```json 102 | { 103 | "accessories": [ 104 | { 105 | "accessory": "HTTP-TEMPERATURE", 106 | "name": "Temperature Sensor", 107 | 108 | "getUrl": { 109 | "url": "http://localhost/api/getTemperature", 110 | "method": "GET" 111 | } 112 | } 113 | ] 114 | } 115 | ``` 116 | 117 | #### UrlObject 118 | 119 | A urlObject can have the following properties: 120 | * `url` \ **required**: Defines the url pointing to your http server 121 | * `method` \ **optional** \(Default: **"GET"**\): Defines the http method used to make the http request 122 | * `body` \ **optional**: Defines the body sent with the http request. If value is not a string it will be 123 | converted to a JSON string automatically. 124 | * `strictSSL` \ **optional** \(Default: **false**\): If enabled the SSL certificate used must be valid and 125 | the whole certificate chain must be trusted. The default is false because most people will work with self signed 126 | certificates in their homes and their devices are already authorized since being in their networks. 127 | * `auth` \ **optional**: If your http server requires authentication you can specify your credential in this 128 | object. When defined the object can contain the following properties: 129 | * `username` \ **required** 130 | * `password` \ **required** 131 | * `sendImmediately` \ **optional** \(Default: **true**\): When set to **true** the plugin will send the 132 | credentials immediately to the http server. This is best practice for basic authentication. 133 | When set to **false** the plugin will send the proper authentication header after receiving an 401 error code 134 | (unauthenticated). The response must include a proper `WWW-Authenticate` header. 135 | Digest authentication requires this property to be set to **false**! 136 | * `headers` \ **optional**: Using this object you can define any http headers which are sent with the http 137 | request. The object must contain only string key value pairs. 138 | * `requestTimeout` \ **optional** \(Default: **20000**\): Time in milliseconds specifying timeout (Time to wait 139 | for http response and also setting socket timeout). 140 | 141 | Below is an example of an urlObject containing the basic properties: 142 | ```json 143 | { 144 | "url": "http://example.com:8080", 145 | "method": "GET", 146 | "body": "exampleBody", 147 | 148 | "strictSSL": false, 149 | 150 | "auth": { 151 | "username": "yourUsername", 152 | "password": "yourPassword" 153 | }, 154 | 155 | "headers": { 156 | "Content-Type": "text/html" 157 | } 158 | } 159 | ``` 160 | 161 | #### MQTTObject 162 | 163 | A mqttObject can have the following properties: 164 | 165 | ##### Basic configuration options: 166 | 167 | * `host` \ **required**: Defines the host of the mqtt broker. 168 | * `port` \ **optional** \(Default: **1883**\): Defines the port of the mqtt broker. 169 | * `credentials` \ **optional**: Defines the credentials used to authenticate with the mqtt broker. 170 | * `username` \ **required** 171 | * `password` \ **optional** 172 | - `subscriptions` \ **required**: Defines an array (or one single object) of subscriptions. 173 | - `topic` \ **required**: Defines the topic to subscribe to. 174 | - `characteristic` \ **required**: Defines the characteristic this subscription updates. 175 | - `messagePattern` \ **optional**: Defines a regex pattern. If `messagePattern` is not specified the 176 | message received will be used as value. If the characteristic expects a boolean value it is tested if the 177 | specified regex is contained in the received message. Otherwise the pattern is matched against the message 178 | and the data from regex group can be extracted using the given `patternGroupToExtract`. 179 | - `patternGroupToExtract` \ **optional** \(Default: **1**\): Defines the regex group of which data is 180 | extracted. 181 | 182 | ##### Advanced configuration options: 183 | 184 | * `protocol` \ **optional** \(Default: **"mqtt"**\): Defines protocol used to connect to the mqtt broker 185 | * `qos` \ **optional** \(Default: **1**\): Defines the Quality of Service (Notice, the QoS of the publisher 186 | must also be configured accordingly). 187 | In contrast to most implementations the default value is **1**. 188 | * `0`: 'At most once' - the message is sent only once and the client and broker take no additional steps to 189 | acknowledge delivery (fire and forget). 190 | * `1`: 'At least once' - the message is re-tried by the sender multiple times until acknowledgement is 191 | received (acknowledged delivery). 192 | * `2`: 'Exactly once' - the sender and receiver engage in a two-level handshake to ensure only one copy of the 193 | message is received (assured delivery). 194 | * `clientId` \ **optional** \(Default: `'mqttjs_' + Math.random().toString(16).substr(2, 8)`\): Defines clientId 195 | * `keepalive` \ **optional** \(Default: **60**\): Time in seconds to send a keepalive. Set to 0 to disable. 196 | * `clean` \ **optional** \(Default: **true**\): Set to false to receive QoS 1 and 2 messages while offline. 197 | * `reconnectPeriod` \ **optional** \(Default: **1000**\): Time in milliseconds after which a reconnect is tried. 198 | * `connectTimeout` \ **optional** \(Default: **30000**\): Time in milliseconds the client waits until the 199 | CONNECT needs to be acknowledged (CONNACK). 200 | 201 | **Note:** Updating values over mqtt is currently only supported for the default unit (celsius). 202 | 203 | Below is an example of an mqttObject containing the basic properties for a temperature service: 204 | ```json 205 | { 206 | "host": "127.0.0.1", 207 | "port": "1883", 208 | 209 | "credentials": { 210 | "username": "yourUsername", 211 | "password": "yourPassword" 212 | }, 213 | 214 | "subscriptions": [ 215 | { 216 | "topic": "your/topic/here", 217 | "characteristic": "CurrentTemperature", 218 | "messagePattern": "(-?[0-9]{1,3}(\\.[0-9]))" 219 | } 220 | ] 221 | } 222 | ``` 223 | 224 | ## Notification Server 225 | 226 | `homebridge-http-temperature-sensor` can be used together with 227 | [homebridge-http-notification-server](https://github.com/Supereg/homebridge-http-notification-server) in order to receive 228 | updates when the state changes at your external program. For details on how to implement those updates and how to 229 | install and configure `homebridge-http-notification-server`, please refer to the 230 | [README](https://github.com/Supereg/homebridge-http-notification-server) of the repository. 231 | 232 | Down here is an example on how to configure `homebridge-http-temperature-sensor` to work with your implementation of the 233 | `homebridge-http-notification-server`. 234 | 235 | ```json 236 | { 237 | "accessories": [ 238 | { 239 | "accessory": "HTTP-TEMPERATURE", 240 | "name": "Temperature Sensor", 241 | 242 | "notificationID": "my-temperature-sensor", 243 | "notificationPassword": "superSecretPassword", 244 | 245 | "getUrl": "http://localhost/api/getTemperature" 246 | } 247 | ] 248 | } 249 | ``` 250 | 251 | * `notificationID` is an per Homebridge instance unique id which must be included in any http request. 252 | * `notificationPassword` is **optional**. It can be used to secure any incoming requests. 253 | 254 | To get more details about the configuration have a look at the 255 | [README](https://github.com/Supereg/homebridge-http-notification-server). 256 | 257 | **Available characteristics (for the POST body)** 258 | 259 | Down here are all characteristics listed which can be updated with an request to the `homebridge-http-notification-server` 260 | 261 | * `characteristic` "CurrentTemperature": expects an float `value` in a range of 0-100 (step 0.1) 262 | --------------------------------------------------------------------------------