diff --git a/config/rzl.js b/config/rzl.js index b504bb7..cc016e9 100644 --- a/config/rzl.js +++ b/config/rzl.js @@ -7,146 +7,150 @@ const config : Config = { color: "orange", mqtt: "ws://map.rzl:1884" }, - topics: { - led_stahltraeger: { - state: "/service/openhab/out/pca301_ledstrips/state", - command: "/service/openhab/in/pca301_ledstrips/command", - defaultValue: "OFF", - values: { on: "ON", off: "OFF" } - }, - snackbar: { - state: "/service/openhab/out/pca301_snackbar/state", - command: "/service/openhab/in/pca301_snackbar/command", - defaultValue: "OFF", - values: { on: "ON", off: "OFF" } - }, - twinkle: { - state: "/service/openhab/out/pca301_twinkle/state", - command: "/service/openhab/in/pca301_twinkle/command", - defaultValue: "OFF", - values: { on: "ON", off: "OFF" } - }, - fan: { - state: "/service/openhab/out/pca301_fan/state", - command: "/service/openhab/in/pca301_fan/command", - defaultValue: "OFF", - values: { on: "ON", off: "OFF" } - }, - videogames: { - state: "/service/openhab/out/pca301_videogames/state", - command: "/service/openhab/in/pca301_videogames/command", - defaultValue: "OFF", - values: { on: "ON", off: "OFF" } - }, - olymp_pc: { - state: "/service/openhab/out/pca301_olymp_pc/state", - command: "/service/openhab/in/pca301_olymp_pc/command", - defaultValue: "OFF", - values: { on: "ON", off: "OFF" } - }, - flyfry: { - state: "/service/openhab/out/wifi_flyfry/state", - command: "/service/openhab/in/wifi_flyfry/command", - defaultValue: "OFF", - values: { on: "ON", off: "OFF" } - }, - artnet: { - state: "/artnet/state", - command: "/artnet/push", - defaultValue: "blackout", - values: { off: "blackout", yellow: "yellow", purple: "purple", - blue: "blue", green: "green", red: "red", random: "random", - cycle: "cycle-random" } - }, - onkyo_connection: { - state: "/service/onkyo/connected", - command: "", - defaultValue: "0", - values: { disconnected: "0", connecting: "1", connected: "2" }, - }, - onkyo_power: { - state: "/service/onkyo/status/system-power", - command: "/service/onkyo/command", - defaultValue: "PWR00", - values: { off: "PWR00", on: "PWR01" }, - parseState: msg => JSON.parse(msg.toString()).onkyo_raw - }, - onkyo_mute: { - state: "/service/onkyo/status/audio-muting", - command: "/service/onkyo/command", - defaultValue: "AMT00", - values: { off: "AMT00", on: "AMT01" }, - parseState: msg => JSON.parse(msg.toString()).onkyo_raw - }, - onkyo_volume: { - state: "/service/onkyo/status/volume", - command: "/service/onkyo/set/volume", - defaultValue: 0, - values: {}, - parseState: msg => JSON.parse(msg.toString()).val - }, - onkyo_inputs: { - state: "/service/onkyo/status/input-selector", - command: "/service/onkyo/command", - defaultValue: "SLI00", - values: { tisch: "SLI11", chromecast: "SLI01", pult: "SLI10", netzwerk: "SLI2B" }, - parseState: msg => JSON.parse(msg.toString()).onkyo_raw - }, - onkyo_radios: { - state: "/service/onkyo/status/latest-NPR", - command: "/service/onkyo/command", - defaultValue: "", - values: { mpd: "NPR01", kohina: "NPR02", somafm_dronezone: "NPR03", somafm_thetrip: "NPR04", - querfunk: "NPR05", somafm_defconradio: "NPR06", somafm_secretagent: "NPR07", somafm_lush: "NPR08", - somafm_beatblender: "NPR09"} - }, - rundumleuchte: { - state: "/service/openhab/out/pca301_rundumleuchte/state", - command: "/service/openhab/in/pca301_rundumleuchte/command", - defaultValue: "OFF", - values: { on: "ON", off: "OFF" } - }, - door_status: { - state: "/service/status", - command: "", - defaultValue: "\"closed\"", - values: { on: "\"open\"", off: "\"closed\"" } - }, - infoscreen: { - state: "/service/openhab/out/pca301_infoscreen/state", - command: "/service/openhab/in/pca301_infoscreen/command", - defaultValue: "OFF", - values: { on: "ON", off: "OFF" } - }, - printer_3d_status: { - state: "/service/ultimaker/state", - command: "", - defaultValue: "unavailable", - values: {}, - parseState: msg => { - switch (msg.toString()) { - case "unreachable": - case "booting": - return "unavailable" - - case "pausing": - case "paused": - case "resuming": - case "wait_cleanup": - case "maintenance": - return "awaiting_interaction" - - case "pre_print": - case "post_print": - case "printing": - return "printing" - - default: - return msg.toString() - } + topics: [ + { + led_stahltraeger: { + state: "/service/openhab/out/pca301_ledstrips/state", + command: "/service/openhab/in/pca301_ledstrips/command", + defaultValue: "OFF", + values: { on: "ON", off: "OFF" } }, - } - }, + snackbar: { + state: "/service/openhab/out/pca301_snackbar/state", + command: "/service/openhab/in/pca301_snackbar/command", + defaultValue: "OFF", + values: { on: "ON", off: "OFF" } + }, + twinkle: { + state: "/service/openhab/out/pca301_twinkle/state", + command: "/service/openhab/in/pca301_twinkle/command", + defaultValue: "OFF", + values: { on: "ON", off: "OFF" } + }, + fan: { + state: "/service/openhab/out/pca301_fan/state", + command: "/service/openhab/in/pca301_fan/command", + defaultValue: "OFF", + values: { on: "ON", off: "OFF" } + }, + videogames: { + state: "/service/openhab/out/pca301_videogames/state", + command: "/service/openhab/in/pca301_videogames/command", + defaultValue: "OFF", + values: { on: "ON", off: "OFF" } + }, + olymp_pc: { + state: "/service/openhab/out/pca301_olymp_pc/state", + command: "/service/openhab/in/pca301_olymp_pc/command", + defaultValue: "OFF", + values: { on: "ON", off: "OFF" } + }, + flyfry: { + state: "/service/openhab/out/wifi_flyfry/state", + command: "/service/openhab/in/wifi_flyfry/command", + defaultValue: "OFF", + values: { on: "ON", off: "OFF" } + }, + artnet: { + state: "/artnet/state", + command: "/artnet/push", + defaultValue: "blackout", + values: { off: "blackout", yellow: "yellow", purple: "purple", + blue: "blue", green: "green", red: "red", random: "random", + cycle: "cycle-random" } + }, + onkyo_connection: { + state: "/service/onkyo/connected", + command: "", + defaultValue: "0", + values: { disconnected: "0", connecting: "1", connected: "2" }, + }, + onkyo_power: { + state: "/service/onkyo/status/system-power", + command: "/service/onkyo/command", + defaultValue: "PWR00", + values: { off: "PWR00", on: "PWR01" }, + parseState: msg => JSON.parse(msg.toString()).onkyo_raw + }, + onkyo_mute: { + state: "/service/onkyo/status/audio-muting", + command: "/service/onkyo/command", + defaultValue: "AMT00", + values: { off: "AMT00", on: "AMT01" }, + parseState: msg => JSON.parse(msg.toString()).onkyo_raw + }, + onkyo_volume: { + state: "/service/onkyo/status/volume", + command: "/service/onkyo/set/volume", + defaultValue: 0, + values: {}, + parseState: msg => JSON.parse(msg.toString()).val + }, + onkyo_inputs: { + state: "/service/onkyo/status/input-selector", + command: "/service/onkyo/command", + defaultValue: "SLI00", + values: { tisch: "SLI11", chromecast: "SLI01", pult: "SLI10", netzwerk: "SLI2B" }, + parseState: msg => JSON.parse(msg.toString()).onkyo_raw + }, + onkyo_radios: { + state: "/service/onkyo/status/latest-NPR", + command: "/service/onkyo/command", + defaultValue: "", + values: { mpd: "NPR01", kohina: "NPR02", somafm_dronezone: "NPR03", somafm_thetrip: "NPR04", + querfunk: "NPR05", somafm_defconradio: "NPR06", somafm_secretagent: "NPR07", somafm_lush: "NPR08", + somafm_beatblender: "NPR09"} + }, + rundumleuchte: { + state: "/service/openhab/out/pca301_rundumleuchte/state", + command: "/service/openhab/in/pca301_rundumleuchte/command", + defaultValue: "OFF", + values: { on: "ON", off: "OFF" } + }, + door_status: { + state: "/service/status", + command: "", + defaultValue: "\"closed\"", + values: { on: "\"open\"", off: "\"closed\"" } + }, + infoscreen: { + state: "/service/openhab/out/pca301_infoscreen/state", + command: "/service/openhab/in/pca301_infoscreen/command", + defaultValue: "OFF", + values: { on: "ON", off: "OFF" } + }, + printer_3d_status: { + state: "/service/ultimaker/state", + command: "", + defaultValue: "unavailable", + values: {}, + parseState: msg => { + switch (msg.toString()) { + case "unreachable": + case "booting": + return "unavailable" + + case "pausing": + case "paused": + case "resuming": + case "wait_cleanup": + case "maintenance": + return "awaiting_interaction" + + case "pre_print": + case "post_print": + case "printing": + return "printing" + + default: + return msg.toString() + } + } + } + }, + utils.esper_topics("afba40", "flyfry"), + utils.esper_topics("afba45", "alarm") + ], controls: { led_stahltrager: { name: "LED Stahlträger", @@ -249,14 +253,14 @@ const config : Config = { position: [450, 590], icon: "fire", iconColor: ({flyfry}) => flyfry == "on" ? "#6666FF" : "#000000", - ui: [ + ui: utils.esper_statistics("flyfry", [ { type: "toggle", text: "Fliegenbratgerät", topic: "flyfry", icon: "power" } - ] + ]) }, artnet: { name: "Artnet", @@ -390,6 +394,13 @@ const config : Config = { } ] }, + alarm: { + name: "Alarm", + position: [340, 250], + icon: "alarm-bell", + iconColor: () => "#000000", + ui: utils.esper_statistics("alarm") + }, door: { name: "Tür", position: [455,350], @@ -406,7 +417,7 @@ const config : Config = { infoscreen: { name: "Infoscreen", position: [255, 495], - icon: "television-guide", + icon: "television-guide flip-v", iconColor: ({infoscreen}) => infoscreen == "on" ? "#4444FF" : "#000000", ui: [ { diff --git a/config/utils.js b/config/utils.js index f778bb9..dbcd6ba 100644 --- a/config/utils.js +++ b/config/utils.js @@ -3,27 +3,81 @@ export const rainbow = "rgba(200,120,120,0.5);" + "--before-background: linear-gradient(40deg, #FF0000 0%, #00FF00 50%, #0000FF 70%, #FFFF00 100%);"; -export const esper_topics = (chip_id: string) => ({ - [ `esper_${chip_id}_version` ]: { +export const esper_topics = (chip_id: string, name: string) => ({ + [ `esper_${name}_version` ]: { state: `/service/esper/${chip_id}/info`, command: "", defaultValue: "UNKNOWN", values: {}, parseState: msg => JSON.parse(msg.toString()).version.esper + }, + [ `esper_${name}_ip` ]: { + state: `/service/esper/${chip_id}/info`, + command: "", + defaultValue: "UNKNOWN", + values: {}, + parseState: msg => JSON.parse(msg.toString()).network.ip + }, + [ `esper_${name}_rssi` ]: { + state: `/service/esper/${chip_id}/info`, + command: "", + defaultValue: "UNKNOWN", + values: {}, + parseState: msg => JSON.parse(msg.toString()).wifi.rssi + }, + [ `esper_${name}_uptime` ]: { + state: `/service/esper/${chip_id}/info`, + command: "", + defaultValue: "UNKNOWN", + values: {}, + parseState: msg => new Date(JSON.parse(msg.toString()).time.startup * 1000) + .toLocaleString() + }, + [ `esper_${name}_device` ]: { + state: `/service/esper/${chip_id}/info`, + command: "", + defaultValue: "UNKNOWN", + values: {}, + parseState: msg => JSON.parse(msg.toString()).device } }); -export const esper_statistics = (chip_id: string, +export const esper_statistics = (name: string, prev_ui: Array = []) => ( prev_ui.concat([ { type: "section", text: "Funkdose" }, + { + type: "text", + text: "Device Variant", + icon: "chart-donut", + topic: `esper_${name}_device` + }, { type: "text", text: "Version", - topic: `esper_${chip_id}_version` + icon: "source-branch", + topic: `esper_${name}_version` + }, + { + type: "text", + text: "IP", + icon: "access-point-network", + topic: `esper_${name}_ip` + }, + { + type: "text", + text: "RSSI", + icon: "wifi", + topic: `esper_${name}_rssi` + }, + { + type: "text", + text: "Running since…", + icon: "av-timer", + topic: `esper_${name}_uptime` } ]) ); diff --git a/src/components/App.js b/src/components/App.js index 45508f5..f9f4760 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -35,7 +35,7 @@ class App extends React.Component { this.state = { selectedControl: null, drawerOpened: false, - mqttState: _.mapValues(props.config.topics, (topic) => ({ + mqttState: _.mapValues(this.topics, (topic) => ({ actual: topic.defaultValue, internal: keyOf(topic.values, topic.defaultValue) })), @@ -44,12 +44,17 @@ class App extends React.Component { onConnect: () => this.setState({ mqttConnected: true }), onReconnect: () => this.setState({ mqttConnected: false }), onDisconnect: () => this.setState({ mqttConnected: false }), - subscribe: _.map(props.config.topics, (x) => x.state) + subscribe: _.map(this.topics, (x) => x.state) }), mqttConnected: false }; } + get topics(): Topics { + return Array.isArray(this.props.config.topics) ? + Object.assign({}, ...this.props.config.topics) : this.props.config.topics; + } + static styles(_theme: Object) { return { drawerPaper: { @@ -67,20 +72,23 @@ class App extends React.Component { } receiveMessage(rawTopic: string, message: Object) { - const topic = _.findKey( - this.props.config.topics, - (v) => v.state === rawTopic + const topics = _.filter( + _.keys(this.topics), + (k) => this.topics[k].state === rawTopic ); - if (topic == null) { + if (topics.length === 0) { return; } - const parseValue = this.props.config.topics[topic].parseState; - const value = parseValue == null ? message.toString() : parseValue(message); - this.setState({mqttState: _.merge(this.state.mqttState, - { [topic]: { - actual: value, - internal: keyOf(this.props.config.topics[topic].values, value) || value - }})}); + for (let i in topics) { + const topic = topics[i]; + const parseValue = this.topics[topic].parseState; + const val = parseValue == null ? message.toString() : parseValue(message); + this.setState({mqttState: _.merge(this.state.mqttState, + { [topic]: { + actual: val, + internal: keyOf(this.topics[topic].values, val) || val + }})}); + } } changeControl(control: ?Control = null) { @@ -92,13 +100,13 @@ class App extends React.Component { } changeState(topic: string, value: Actual) { - const rawTopic = this.props.config.topics[topic].command; + const rawTopic = this.topics[topic].command; if (rawTopic == null) { return; } this.state.mqttSend( rawTopic, - String(this.props.config.topics[topic].values[value] || value) + String(this.topics[topic].values[value] || value) ); } diff --git a/src/components/UiItemList/UiItem.js b/src/components/UiItemList/UiItem.js index 054308f..d48edaa 100644 --- a/src/components/UiItemList/UiItem.js +++ b/src/components/UiItemList/UiItem.js @@ -209,8 +209,8 @@ export class Section extends UiItem { export class Text extends UiControl { render() { return [ - , - + , + ]; } } diff --git a/types/types.js b/types/types.js index 8dba59b..7dfeb0b 100644 --- a/types/types.js +++ b/types/types.js @@ -111,7 +111,7 @@ declare type Controls = Map; declare type Config = { space: Space, - topics: Topics, + topics: Topics | Array, controls: Controls, layers: Array };