Skip to content

Commit

Permalink
Merge pull request #11 from raintonr/10-name-devices-if-mac-address-a…
Browse files Browse the repository at this point in the history
…vailable-in-net-tools

10 name devices if mac address available in net tools
  • Loading branch information
raintonr authored Dec 27, 2022
2 parents 4f7f156 + 4351d62 commit 3903315
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 22 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ Make sure to linkage in the events you would like to report to ioBroker includes
### **WORK IN PROGRESS**
-->

### **WORK IN PROGRESS**
- (Robin Rainton) Try to derive device names from net-tools. Optionally use channelName from devices ([#10](https://github.com/raintonr/ioBroker.hikvision-alarmserver/issues/10)).

### 0.0.6 (2022-12-13)
- (Robin Rainton) Handle multipart message payload ([#5](https://github.com/raintonr/ioBroker.hikvision-alarmserver/issues/5)).
- (Robin Rainton) Handle payloads without XML declaration ([#7](https://github.com/raintonr/ioBroker.hikvision-alarmserver/issues/7).)
Expand Down
11 changes: 8 additions & 3 deletions admin/index_m.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,21 @@
</div>
</div>

<!-- Put your content here -->

<!-- For example columns with settings: -->
<div class="row">
<div class="col s6 input-field">
<input type="text" class="value" id="port" />
<label for="option2" class="translate">Listen port</label>
</div>
</div>

<div class="row">
<div class="col s6 input-field">
<input type="checkbox" class="value" id="useChannels" />
<span class="translate">Create channels below devices</span>
<br/>
<span class="translate">Useful if you have devices that have more than one sensor.</span>
</div>
</div>
</div>

</body>
Expand Down
3 changes: 2 additions & 1 deletion io-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@
]
},
"native": {
"port": 8089
"port": 8089,
"useChannels": false
},
"objects": [],
"instanceObjects": []
Expand Down
82 changes: 64 additions & 18 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,53 +153,99 @@ class HikvisionAlarmserver extends utils.Adapter {
}

async logEvent(xml) {
let deviceId = null;
let macAddress = null;
let eventType = null;
try {
/* This is inside a try...catch so we handle case when XML was bad */
/* TODO: make object names configurable? Mac? IP? etc. */
deviceId = xml.EventNotificationAlert.macAddress;
eventType = xml.EventNotificationAlert.eventType;
// This is inside a try...catch so we handle case when XML was bad.
// TODO: make object names configurable? Mac? IP? etc.
macAddress = xml.EventNotificationAlert.macAddress[0];
eventType = xml.EventNotificationAlert.eventType[0];
} catch (err) {
this.log.error('Bad request - failed to find required XML attributes');
return;
}

// Channel name is optional
const channelName = this.config.useChannels && xml.EventNotificationAlert?.channelName ?
xml.EventNotificationAlert.channelName[0] : null;

// Strip colons from ID to be consistent with net-tools
const id = String(deviceId).replace(/:/g, '') + '.' + eventType;
const device = String(macAddress).replace(/:/g, '');
const stateId = device +
(channelName != null ? '.' + channelName : '') +
('.' + eventType);

// Cancel any existing timer for this state
if (id in this.timers) {
if (this.timers[id]) {
this.clearTimeout(this.timers[id]);
this.timers[id] = null;
if (stateId in this.timers) {
if (this.timers[stateId]) {
this.clearTimeout(this.timers[stateId]);
this.timers[stateId] = null;
}
} else {
// Create state if not there...
// Create device/channels/state if not there...
// ... which will only be attempted if not in timers as if this ID is in the
// timers object we must have already seen it and created the state.
this.log.debug('Creating state ' + id);
await this.setObjectNotExistsAsync(id, {

this.log.debug('Creating device ' + device);
const native = {
mac: macAddress
};
// Add optional parts
if (xml.EventNotificationAlert?.ipAddress) {
native.ipAddress = xml.EventNotificationAlert.ipAddress[0];
}
await this.setObjectNotExistsAsync(device, {
type: 'device',
common: {
name: await this.getDeviceName(device)
},
native: native
});

if (channelName != null) {
this.log.debug('Creating channel ' + channelName);
await this.createChannelAsync(device, channelName);
}

this.log.debug('Creating state ' + stateId);
await this.setObjectNotExistsAsync(stateId, {
type: 'state',
common: {
name: eventType,
type: 'boolean',
role: 'indicator',
read: true,
write: true,
write: false,
},
native: {},
});
}

// Set it true (event in progress)
await this.setStateChangedAsync(id, true, true);
await this.setStateChangedAsync(stateId, true, true);

// ... and restart to clear (set false) after 5s
this.timers[id] = this.setTimeout(() => {
this.setState(id, false, true);
this.timers[id] = null;
this.timers[stateId] = this.setTimeout(() => {
this.setState(stateId, false, true);
this.timers[stateId] = null;
}, 5000 /* TODO: make timeout option? */);
}

async getDeviceName(device) {
// Output is same as input by default
let output = device;

const devices = await this.getForeignObjectsAsync('net-tools.*.' + device, 'device');
if (Object.keys(devices).length == 1) {
// As expected, return the device name...
const device = devices[Object.keys(devices)[0]];
if (device && device.common && device.common.name) {
// ... which should always be here.
output = device.common.name;
}
}
return output;
}
}

if (require.main !== module) {
Expand Down

0 comments on commit 3903315

Please sign in to comment.