Added support for values in Z-Wave web panel (see #123)
This commit is contained in:
parent
a0ceb560b4
commit
98727c4f31
9 changed files with 356 additions and 144 deletions
|
@ -17,6 +17,7 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
|
||||
.no-items {
|
||||
padding: 2em;
|
||||
|
@ -156,7 +157,69 @@
|
|||
display: inline-block;
|
||||
width: 58%;
|
||||
text-align: right;
|
||||
|
||||
.value-edit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.value-data {
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.slider-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.unit {
|
||||
font-size: .8em;
|
||||
margin-left: 1em;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
select {
|
||||
width: 100%;
|
||||
border-radius: 2em;
|
||||
}
|
||||
|
||||
.numeric {
|
||||
input.slider {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.row {
|
||||
background: none;
|
||||
&:hover {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
.value-min, .value-max {
|
||||
width: 50%;
|
||||
font-size: .85em;
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
.value-min {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.value-max {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-value-name-edit {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modal {
|
||||
|
|
|
@ -6,7 +6,8 @@ Vue.component('toggle-switch', {
|
|||
toggled: function(event) {
|
||||
this.$emit('toggled', {
|
||||
id: this.id,
|
||||
value: !this.value
|
||||
value: !this.value,
|
||||
event: event,
|
||||
});
|
||||
},
|
||||
},
|
||||
|
|
|
@ -10,31 +10,30 @@ Vue.component('zwave', {
|
|||
nodes: {},
|
||||
groups: {},
|
||||
scenes: {},
|
||||
values: {},
|
||||
switches: new Set(),
|
||||
dimmers: new Set(),
|
||||
sensors: new Set(),
|
||||
batteryLevels: new Set(),
|
||||
powerLevels: new Set(),
|
||||
bulbs: new Set(),
|
||||
doorlocks: new Set(),
|
||||
usercodes: new Set(),
|
||||
thermostats: new Set(),
|
||||
protections: new Set(),
|
||||
commandRunning: false,
|
||||
values: {
|
||||
switches: {},
|
||||
dimmers: {},
|
||||
sensors: {},
|
||||
battery_levels: {},
|
||||
power_levels: {},
|
||||
bulbs: {},
|
||||
doorlocks: {},
|
||||
usercodes: {},
|
||||
thermostats: {},
|
||||
protections: {},
|
||||
},
|
||||
selected: {
|
||||
view: 'nodes',
|
||||
nodeId: undefined,
|
||||
groupId: undefined,
|
||||
sceneId: undefined,
|
||||
valueId: undefined,
|
||||
},
|
||||
loading: {
|
||||
status: false,
|
||||
nodes: false,
|
||||
groups: false,
|
||||
scenes: false,
|
||||
values: false,
|
||||
},
|
||||
modal: {
|
||||
networkInfo: {
|
||||
|
@ -198,28 +197,11 @@ Vue.component('zwave', {
|
|||
methods: {
|
||||
refreshNodes: async function () {
|
||||
this.loading.nodes = true;
|
||||
this.loading.values = true;
|
||||
|
||||
this.nodes = await request('zwave.get_nodes');
|
||||
this.loading.nodes = false;
|
||||
|
||||
this.values = Object.values(this.nodes).reduce((values, node) => {
|
||||
values = {
|
||||
...Object.values(node.values).reduce((values, value) => {
|
||||
values[value.value_id] = {
|
||||
node_id: node.node_id,
|
||||
...value,
|
||||
};
|
||||
|
||||
return values;
|
||||
}, {}),
|
||||
...values
|
||||
};
|
||||
|
||||
return values;
|
||||
}, {});
|
||||
|
||||
this.loading.values = false;
|
||||
if (Object.keys(this.nodes).length) {
|
||||
Vue.set(this.views, 'values', true);
|
||||
}
|
||||
},
|
||||
|
||||
refreshGroups: async function () {
|
||||
|
@ -250,93 +232,16 @@ Vue.component('zwave', {
|
|||
this.loading.scenes = false;
|
||||
},
|
||||
|
||||
refreshSwitches: async function () {
|
||||
this.switches = new Set(Object.values(await request('zwave.get_switches'))
|
||||
.filter((sw) => sw.id_on_network).map((sw) => sw.value_id));
|
||||
refreshValues: async function(type) {
|
||||
Vue.set(this.values, type, Object.values(await request('zwave.get_' + type))
|
||||
.filter((item) => item.id_on_network)
|
||||
.reduce((values, value) => {
|
||||
values[value.id_on_network] = true;
|
||||
return values;
|
||||
}, {}));
|
||||
|
||||
if (this.switches.size) {
|
||||
Vue.set(this.views, 'switches', true);
|
||||
}
|
||||
},
|
||||
|
||||
refreshDimmers: async function () {
|
||||
this.dimmers = new Set(Object.values(await request('zwave.get_dimmers'))
|
||||
.filter((dimmer) => dimmer.id_on_network).map((dimmer) => dimmer.value_id));
|
||||
|
||||
if (this.dimmers.size) {
|
||||
Vue.set(this.views, 'dimmers', true);
|
||||
}
|
||||
},
|
||||
|
||||
refreshSensors: async function () {
|
||||
this.sensors = new Set(Object.values(await request('zwave.get_sensors'))
|
||||
.filter((sensor) => sensor.id_on_network).map((sensor) => sensor.value_id));
|
||||
|
||||
if (this.sensors.size) {
|
||||
Vue.set(this.views, 'sensors', true);
|
||||
}
|
||||
},
|
||||
|
||||
refreshBatteryLevels: async function () {
|
||||
this.batteryLevels = new Set(Object.values(await request('zwave.get_battery_levels'))
|
||||
.filter((battery) => battery.id_on_network).map((battery) => battery.value_id));
|
||||
|
||||
if (this.batteryLevels.size) {
|
||||
Vue.set(this.views, 'batteryLevels', true);
|
||||
}
|
||||
},
|
||||
|
||||
refreshPowerLevels: async function () {
|
||||
this.powerLevels = new Set(Object.values(await request('zwave.get_power_levels'))
|
||||
.filter((power) => power.id_on_network).map((power) => power.value_id));
|
||||
|
||||
if (this.powerLevels.size) {
|
||||
Vue.set(this.views, 'powerLevels', true);
|
||||
}
|
||||
},
|
||||
|
||||
refreshBulbs: async function () {
|
||||
this.bulbs = new Set(Object.values(await request('zwave.get_bulbs'))
|
||||
.filter((bulb) => bulb.id_on_network).map((bulb) => bulb.value_id));
|
||||
|
||||
if (this.bulbs.size) {
|
||||
Vue.set(this.views, 'bulbs', true);
|
||||
}
|
||||
},
|
||||
|
||||
refreshDoorlocks: async function () {
|
||||
this.doorlocks = new Set(Object.values(await request('zwave.get_doorlocks'))
|
||||
.filter((lock) => lock.id_on_network).map((lock) => lock.value_id));
|
||||
|
||||
if (this.doorlocks.size) {
|
||||
Vue.set(this.views, 'doorlocks', true);
|
||||
}
|
||||
},
|
||||
|
||||
refreshUsercodes: async function () {
|
||||
this.doorlocks = new Set(Object.values(await request('zwave.get_usercodes'))
|
||||
.filter((code) => code.id_on_network).map((code) => code.value_id));
|
||||
|
||||
if (this.usercodes.size) {
|
||||
Vue.set(this.views, 'usercodes', true);
|
||||
}
|
||||
},
|
||||
|
||||
refreshThermostats: async function () {
|
||||
this.thermostats = new Set(Object.values(await request('zwave.get_thermostats'))
|
||||
.filter((th) => th.id_on_network).map((th) => th.value_id));
|
||||
|
||||
if (this.thermostats.size) {
|
||||
Vue.set(this.views, 'thermostats', true);
|
||||
}
|
||||
},
|
||||
|
||||
refreshProtections: async function () {
|
||||
this.protections = new Set(Object.values(await request('zwave.get_protections'))
|
||||
.filter((p) => p.id_on_network).map((p) => p.value_id));
|
||||
|
||||
if (this.protections.size) {
|
||||
Vue.set(this.views, 'protections', true);
|
||||
if (Object.keys(this.values[type]).length) {
|
||||
Vue.set(this.views, type, true);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -355,16 +260,17 @@ Vue.component('zwave', {
|
|||
this.refreshNodes();
|
||||
this.refreshGroups();
|
||||
this.refreshScenes();
|
||||
this.refreshSwitches();
|
||||
this.refreshDimmers();
|
||||
this.refreshSensors();
|
||||
this.refreshBulbs();
|
||||
this.refreshDoorlocks();
|
||||
this.refreshUsercodes();
|
||||
this.refreshThermostats();
|
||||
this.refreshProtections();
|
||||
this.refreshBatteryLevels();
|
||||
this.refreshPowerLevels();
|
||||
this.refreshValues('switches');
|
||||
this.refreshValues('dimmers');
|
||||
this.refreshValues('sensors');
|
||||
this.refreshValues('bulbs');
|
||||
this.refreshValues('doorlocks');
|
||||
this.refreshValues('usercodes');
|
||||
this.refreshValues('thermostats');
|
||||
this.refreshValues('protections');
|
||||
this.refreshValues('battery_levels');
|
||||
this.refreshValues('power_levels');
|
||||
this.refreshValues('node_config');
|
||||
this.refreshStatus();
|
||||
},
|
||||
|
||||
|
@ -428,6 +334,8 @@ Vue.component('zwave', {
|
|||
|
||||
created: function() {
|
||||
const self = this;
|
||||
this.bus.$on('refresh', this.refresh);
|
||||
this.bus.$on('refreshNodes', this.refreshNodes);
|
||||
this.bus.$on('nodeClicked', this.onNodeClicked);
|
||||
this.bus.$on('groupClicked', this.onGroupClicked);
|
||||
this.bus.$on('openAddToGroupModal', () => {self.modal.group.visible = true});
|
||||
|
@ -447,7 +355,11 @@ Vue.component('zwave', {
|
|||
'platypush.message.event.zwave.ZwaveNodeEvent',
|
||||
'platypush.message.event.zwave.ZwaveNodeAddedEvent',
|
||||
'platypush.message.event.zwave.ZwaveNodeRenamedEvent',
|
||||
'platypush.message.event.zwave.ZwaveNodeReadyEvent');
|
||||
'platypush.message.event.zwave.ZwaveNodeReadyEvent',
|
||||
'platypush.message.event.zwave.ZwaveValueAddedEvent',
|
||||
'platypush.message.event.zwave.ZwaveValueChangedEvent',
|
||||
'platypush.message.event.zwave.ZwaveValueRemovedEvent',
|
||||
'platypush.message.event.zwave.ZwaveValueRefreshedEvent');
|
||||
},
|
||||
|
||||
mounted: function() {
|
||||
|
|
73
platypush/backend/http/static/js/plugins/zwave/value.js
Normal file
73
platypush/backend/http/static/js/plugins/zwave/value.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
Vue.component('zwave-value', {
|
||||
template: '#tmpl-zwave-value',
|
||||
props: ['node','bus','selected','values'],
|
||||
data: function() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
onNodeClicked: function() {
|
||||
this.bus.$emit('nodeClicked', {
|
||||
nodeId: this.node.node_id,
|
||||
});
|
||||
},
|
||||
|
||||
disableForm: function(form) {
|
||||
form.querySelector('input,button').readOnly = true;
|
||||
},
|
||||
|
||||
enableForm: function(form) {
|
||||
form.querySelector('input,button').readOnly = false;
|
||||
},
|
||||
|
||||
onEditMode: function(mode) {
|
||||
Vue.set(this.editMode, mode, true);
|
||||
const form = this.$refs[mode + 'Form'];
|
||||
const input = form.querySelector('input[type=text]');
|
||||
|
||||
setTimeout(() => {
|
||||
input.focus();
|
||||
input.select();
|
||||
}, 10);
|
||||
},
|
||||
|
||||
editName: function(event) {
|
||||
const value = this.node.values[event.target.parentElement.dataset.idOnNetwork];
|
||||
const name = prompt('New name', value.label);
|
||||
|
||||
if (!name || !name.length || name === value.label) {
|
||||
return;
|
||||
}
|
||||
|
||||
request('zwave.set_value_label', {
|
||||
id_on_network: value.id_on_network,
|
||||
new_label: name,
|
||||
}).then(() => {
|
||||
this.bus.$emit('refreshNodes');
|
||||
createNotification({
|
||||
text: 'Value successfully renamed',
|
||||
image: { icon: 'check' }
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
onValueChanged: function(event) {
|
||||
const target = event.target ? event.target : event.event.target.parentElement;
|
||||
const value = this.node.values[target.dataset.idOnNetwork];
|
||||
const data = value.type === 'List' ? value.data_items[event.target.value] : (target.value || event.value);
|
||||
|
||||
request('zwave.set_value', {
|
||||
id_on_network: value.id_on_network,
|
||||
data: data,
|
||||
}).then(() => {
|
||||
this.bus.$emit('refreshNodes');
|
||||
createNotification({
|
||||
text: 'Value successfully modified',
|
||||
image: { icon: 'check' }
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
{% include 'plugins/zwave/node.html' %}
|
||||
{% include 'plugins/zwave/group.html' %}
|
||||
{% include 'plugins/zwave/value.html' %}
|
||||
|
||||
<script type="text/x-template" id="tmpl-zwave">
|
||||
<div class="zwave-container">
|
||||
|
@ -10,7 +11,7 @@
|
|||
<div class="view-selector col-s-9 col-m-10 col-l-11">
|
||||
<select @change="onViewChange">
|
||||
<option v-for="_, view in views"
|
||||
v-text="view[0].toUpperCase() + view.slice(1)"
|
||||
v-text="(view[0].toUpperCase() + view.slice(1)).replace('_', ' ')"
|
||||
:key="view"
|
||||
:selected="view == selected.view"
|
||||
:value="view">
|
||||
|
@ -65,7 +66,7 @@
|
|||
</zwave-node>
|
||||
</div>
|
||||
|
||||
<div class="view groups" v-if="selected.view == 'groups'">
|
||||
<div class="view groups" v-else-if="selected.view == 'groups'">
|
||||
<div class="no-items" v-if="Object.keys(groups).length == 0">
|
||||
<div class="loading" v-if="loading.groups">Loading groups...</div>
|
||||
<div class="empty" v-else>No groups available on the network</div>
|
||||
|
@ -81,7 +82,7 @@
|
|||
</zwave-group>
|
||||
</div>
|
||||
|
||||
<div class="view scenes" v-if="selected.view == 'scenes'">
|
||||
<div class="view scenes" v-else-if="selected.view == 'scenes'">
|
||||
<div class="no-items" v-if="Object.keys(scenes).length == 0">
|
||||
<div class="loading" v-if="loading.scenes">Loading scenes...</div>
|
||||
<div class="empty" v-else>No scenes configured on the network</div>
|
||||
|
@ -94,6 +95,23 @@
|
|||
<!-- :bus="bus">-->
|
||||
<!-- </zwave-scene>-->
|
||||
</div>
|
||||
|
||||
<div class="view values" v-else>
|
||||
<div class="no-items" v-if="Object.keys(nodes).length == 0">
|
||||
<div class="loading" v-if="loading.nodes">Loading nodes...</div>
|
||||
<div class="empty" v-else>No nodes found on the network</div>
|
||||
</div>
|
||||
|
||||
<zwave-value
|
||||
v-for="node, nodeId in nodes"
|
||||
v-if="selected.view === 'values' || Object.values(node.values).filter((value) => value.id_on_network in values[selected.view]).length > 0"
|
||||
:key="nodeId"
|
||||
:values="Object.values(node.values).filter((value) => selected.view === 'values' || value.id_on_network in values[selected.view]).map((value) => value.id_on_network)"
|
||||
:node="node"
|
||||
:selected="selected.nodeId == nodeId"
|
||||
:bus="bus">
|
||||
</zwave-value>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
|
110
platypush/backend/http/templates/plugins/zwave/value.html
Normal file
110
platypush/backend/http/templates/plugins/zwave/value.html
Normal file
|
@ -0,0 +1,110 @@
|
|||
<script type="text/x-template" id="tmpl-zwave-value">
|
||||
<div class="item node" :class="{selected: selected}">
|
||||
<div class="row name vertical-center" :class="{selected: selected}"
|
||||
v-text="node.name" @click="onNodeClicked"></div>
|
||||
|
||||
<div class="params" v-if="selected">
|
||||
<div class="section value"
|
||||
v-for="value in node.values"
|
||||
v-if="values.indexOf(value.id_on_network) >= 0"
|
||||
:key="value.id_on_network">
|
||||
<div class="header">
|
||||
<div class="title">
|
||||
<button class="btn btn-default btn-value-name-edit" title="Edit value name"
|
||||
:data-id-on-network="value.id_on_network" @click="editName">
|
||||
<i class="fa fa-edit"></i>
|
||||
</button>
|
||||
{% raw %}{{ value.label }}{% endraw %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
<div class="row">
|
||||
<div class="param-name">Value</div>
|
||||
<div class="param-value">
|
||||
<div class="value-view" v-if="value.is_read_only">
|
||||
<div class="value-data" v-text="value.data" ></div>
|
||||
<div class="unit" v-text="value.units" v-if="value.units && value.units.length">
|
||||
{% raw %}{{ value.units }}{% endraw %}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="value-edit" v-else>
|
||||
<div :class="['col-' + (value.units && value.units.length ? '11' : '12')]">
|
||||
<div class="list" v-if="value.type === 'List'">
|
||||
<select @change="onValueChanged"
|
||||
:data-id-on-network="value.id_on_network">
|
||||
<option v-for="data, index in value.data_items"
|
||||
v-text="data"
|
||||
:key="index"
|
||||
:selected="value.data == data"
|
||||
:value="index">
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="numeric slider-container" v-else-if="['Byte', 'Decimal', 'Short'].indexOf(value.type) >= 0">
|
||||
<div class="col-10">
|
||||
<div class="row">
|
||||
<span class="value-min" v-text="value.min"></span>
|
||||
<span class="value-max" v-text="value.max"></span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<input class="slider" type="range" :min="value.min" :max="value.max"
|
||||
:value="value.data" :data-id-on-network="value.id_on_network"
|
||||
@change="onValueChanged">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<input type="text" :data-id-on-network="value.id_on_network" :value="value.data"
|
||||
@change="onValueChanged">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="boolean" v-else-if="['Bool', 'Button'].indexOf(value.type) >= 0">
|
||||
<toggle-switch :value="value.data" :data-id-on-network="value.id_on_network"
|
||||
@toggled="onValueChanged"></toggle-switch>
|
||||
</div>
|
||||
|
||||
<div class="value-data" v-text="value.data" v-else></div>
|
||||
</div>
|
||||
|
||||
<div class="col-1 unit" v-text="value.units" v-if="value.units && value.units.length">
|
||||
{% raw %}{{ value.units }}{% endraw %}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" v-if="value.help && value.help.length">
|
||||
<div class="param-name">Help</div>
|
||||
<div class="param-value" v-text="value.help"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="param-name">Value ID</div>
|
||||
<div class="param-value" v-text="value.value_id"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="param-name">ID on Network</div>
|
||||
<div class="param-value" v-text="value.id_on_network"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="param-name">Command Class</div>
|
||||
<div class="param-value" v-text="value.command_class"></div>
|
||||
</div>
|
||||
|
||||
<div class="row" v-if="value.last_update">
|
||||
<div class="param-name">Last Update</div>
|
||||
<div class="param-value" v-text="value.last_update"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="application/javascript" src="{{ url_for('static', filename='js/plugins/zwave/value.js') }}"></script>
|
||||
|
|
@ -241,6 +241,8 @@ class ZwaveBackend(Backend):
|
|||
event = ZwaveValueRemovedEvent(device=self.device,
|
||||
node=ZwavePlugin.node_to_dict(event.args['node']),
|
||||
value=ZwavePlugin.value_to_dict(event.args['value']))
|
||||
else:
|
||||
self.logger.info('Received unhandled ZWave event: {}'.format(event))
|
||||
|
||||
if isinstance(event, ZwaveEvent):
|
||||
self.bus.post(event)
|
||||
|
|
|
@ -17,6 +17,9 @@ class Message(object):
|
|||
isinstance(obj, datetime.time):
|
||||
return obj.isoformat()
|
||||
|
||||
if isinstance(obj, set):
|
||||
return list(obj)
|
||||
|
||||
return super().default(obj)
|
||||
|
||||
def __init__(self, timestamp=None, *args, **kwargs):
|
||||
|
|
|
@ -150,13 +150,14 @@ class ZwavePlugin(Plugin):
|
|||
controller.request_node_neighbor_update(node.node_id)
|
||||
|
||||
@staticmethod
|
||||
def value_to_dict(value) -> Dict[str, Any]:
|
||||
def value_to_dict(value: Optional[ZWaveValue]) -> Dict[str, Any]:
|
||||
if not value:
|
||||
return {}
|
||||
|
||||
return {
|
||||
'command_class': value.command_class,
|
||||
'command_class': value.node.get_command_class_as_string(value.command_class),
|
||||
'data': value.data,
|
||||
'data_as_string': value.data_as_string,
|
||||
'data_items': list(value.data_items) if isinstance(value.data_items, set) else value.data_items,
|
||||
'genre': value.genre,
|
||||
'help': value.help,
|
||||
|
@ -185,7 +186,7 @@ class ZwavePlugin(Plugin):
|
|||
}
|
||||
|
||||
@staticmethod
|
||||
def group_to_dict(group) -> Dict[str, Any]:
|
||||
def group_to_dict(group: Optional[ZWaveGroup]) -> Dict[str, Any]:
|
||||
if not group:
|
||||
return {}
|
||||
|
||||
|
@ -197,7 +198,7 @@ class ZwavePlugin(Plugin):
|
|||
}
|
||||
|
||||
@classmethod
|
||||
def node_to_dict(cls, node) -> Dict[str, Any]:
|
||||
def node_to_dict(cls, node: Optional[ZWaveNode]) -> Dict[str, Any]:
|
||||
if not node:
|
||||
return {}
|
||||
|
||||
|
@ -240,7 +241,7 @@ class ZwavePlugin(Plugin):
|
|||
'use_cache': node.use_cache,
|
||||
'version': node.version,
|
||||
'values': {
|
||||
value_id: cls.value_to_dict(value)
|
||||
value.id_on_network: cls.value_to_dict(value)
|
||||
for value_id, value in (node.values or {}).items()
|
||||
},
|
||||
}
|
||||
|
@ -445,16 +446,22 @@ class ZwavePlugin(Plugin):
|
|||
node_id: Optional[int] = None, node_name: Optional[str] = None, value_label: Optional[str] = None) \
|
||||
-> ZWaveValue:
|
||||
assert (value_id is not None or id_on_network is not None) or \
|
||||
(node_id is not None and node_name is not None and value_label is not None),\
|
||||
((node_id is not None or node_name is not None) and value_label is not None),\
|
||||
'Specify either value_id, id_on_network, or [node_id/node_name, value_label]'
|
||||
|
||||
if value_id is not None:
|
||||
return self._get_network().get_value(value_id)
|
||||
if id_on_network is not None:
|
||||
return self._get_network().get_value_from_id_on_network(id_on_network)
|
||||
values = [value
|
||||
for node in self._get_network().nodes.values()
|
||||
for value in node.values.values()
|
||||
if value.id_on_network == id_on_network]
|
||||
|
||||
assert values, 'No such value ID: {}'.format(id_on_network)
|
||||
return values[0]
|
||||
|
||||
node = self._get_node(node_id=node_id, node_name=node_name)
|
||||
values = [v for v in node.values if v.label == value_label]
|
||||
values = [v for v in node.values.values() if v.label == value_label]
|
||||
assert values, 'No such value on node "{}": "{}"'.format(node.name, value_label)
|
||||
return values[0]
|
||||
|
||||
|
@ -489,7 +496,30 @@ class ZwavePlugin(Plugin):
|
|||
"""
|
||||
value = self._get_value(value_id=value_id, id_on_network=id_on_network,
|
||||
node_id=node_id, node_name=node_name, value_label=value_label)
|
||||
value.data = data
|
||||
new_val = value.check_data(data)
|
||||
assert new_val is not None, 'Invalid value passed to the property'
|
||||
node: ZWaveNode = self._get_network().nodes[value.node.node_id]
|
||||
node.values[value.value_id].data = new_val
|
||||
self.write_config()
|
||||
|
||||
@action
|
||||
def set_value_label(self, new_label: str, value_id: Optional[int] = None, id_on_network: Optional[str] = None,
|
||||
value_label: Optional[str] = None, node_id: Optional[int] = None,
|
||||
node_name: Optional[str] = None):
|
||||
"""
|
||||
Change the label/name of a value.
|
||||
|
||||
:param new_label: New value label.
|
||||
:param value_id: Select value by value_id.
|
||||
:param id_on_network: Select value by id_on_network.
|
||||
:param value_label: Select value by [node_id/node_name, value_label]
|
||||
:param node_id: Select value by [node_id/node_name, value_label]
|
||||
:param node_name: Select value by [node_id/node_name, value_label]
|
||||
"""
|
||||
value = self._get_value(value_id=value_id, id_on_network=id_on_network,
|
||||
node_id=node_id, node_name=node_name, value_label=value_label)
|
||||
value.label = new_label
|
||||
self.write_config()
|
||||
|
||||
@action
|
||||
def node_add_value(self, value_id: Optional[int] = None, id_on_network: Optional[str] = None,
|
||||
|
@ -579,7 +609,7 @@ class ZwavePlugin(Plugin):
|
|||
else self._get_network().nodes.values()
|
||||
|
||||
return {
|
||||
value_id: {
|
||||
value.id_on_network: {
|
||||
'node_id': node.node_id,
|
||||
'node_name': node.name,
|
||||
**self.value_to_dict(value)
|
||||
|
|
Loading…
Reference in a new issue