BACnet scheduler
-
Hi
I am looking to export from my controller a scheduler that I can import on Mango and further integrate on my HTML page.
I saw some discussion in 2015 but I understand that the new BACnet module was upgraded in V3.
Do you have any example to share ?
Thanks
Mircea -
Hi Mircea,
We haven't gotten to adding full schedule support into the BACnet module yet. It's on our road map though!
-
Hi @phildunlap , any updates on the progress of adding full schedule support into the BACnet module?
-
Hi ddiezperez,
Certainly steps have been taken. If you notice in the latest version of the BACnet module, you can select schedule as an point's object type and you can poll for the WeeklySchedule property of it but cannot yet set out a schedule through a place in the UI. The API does have sufficient support that you can write a schedule object's various properties, I'd encourage you to check out the API on swagger. Your env.properties setting for
swagger.mangoApiVersion=v[12]
and then you would be seeking the/rest/v2/bacnet/bulk
endpoints. Edit: for an example write to this endpoint, see my later postIn the email you sent to support you also asked about Calendar objects, which are in the same state. You can poll for any property of a calendar object, but you cannot set to it through data points currently.
Here's a rough script I wrote in Mango's scripting environments that set out a schedule (will attempt to do so even from just the validate button):
//Get the local device config from a configured bacnet data source. var localDeviceConfig = com.serotonin.m2m2.db.dao.DataSourceDao.instance.getByXid("DS_354e2188-4867-431b-9051-bca39b011ed7").getLocalDeviceConfig(); localDeviceConfig = com.serotonin.ma.bacnet.device.LocalDeviceDwr.getLocalDevice(localDeviceConfig); var listener = new com.serotonin.ma.bacnet.ScriptableDeviceEventListener(); listener.registerListenerExceptionHandler( function(excp) { print("Listener Exception"); }); listener.registerIAmReceivedHandler( function(removeDevice) {print("Remote device");}); listener.registerAllowPropertyWriteHandler( function(from, obj, pv) {print("Allow property write");}); listener.registerPropertyWrittenHandler( function(from, obj, pv) {print("Property written");}); listener.registerIHaveReceivedHandler( function(removeDevice, removeObject) {print("I have received");}); listener.registerCovNotificationReceivedHandler( function(subIdentifier, initDeviceIdentifier, monitoredObjectIdentifier, timeRemaining, listOfValues) {print("COV notification");}); listener.registerEventNotificationReceivedHandler( function(processIdentifier, initDeviceIdentifier, eventObjectIdentifier, timestamp, notificationClass, priority, eventType, messageText, notifyType, ackRequired, fromState, toState, eventValues) {print("Register event notification received");}); listener.registerTextMessageReceivedHandler( function(textMessageSourceDevice, messageClass, messagePriority, message) {print("Text message received");}); listener.registerSynchronizeTimeHandler( function(from, dateTime, utc) {print("Sync time received");}); listener.registerRequestReceivedHandler( function(from, service) {print("Request received");}); var localDevice = com.serotonin.ma.bacnet.device.LocalDeviceFactory.getLocalDevice(localDeviceConfig, listener); //print(localDevice); function createTimeValue(pos) { switch(pos) { case 0 : return new com.serotonin.bacnet4j.type.constructed.TimeValue( new com.serotonin.bacnet4j.type.primitive.Time(0, 0, 0, 0), com.serotonin.bacnet4j.type.primitive.Boolean.TRUE ); case 1 : return new com.serotonin.bacnet4j.type.constructed.TimeValue( new com.serotonin.bacnet4j.type.primitive.Time(10, 0, 0, 0), com.serotonin.bacnet4j.type.primitive.Boolean.FALSE ); case 2 : return new com.serotonin.bacnet4j.type.constructed.TimeValue( new com.serotonin.bacnet4j.type.primitive.Time(12, 0, 0, 0), com.serotonin.bacnet4j.type.primitive.Boolean.TRUE ); } } //Okay, we have the device and the listener, let's try to set a schedule object out.... var schedule = new com.serotonin.bacnet4j.type.constructed.BACnetArray(7, new com.serotonin.bacnet4j.type.constructed.DailySchedule( new com.serotonin.bacnet4j.type.constructed.SequenceOf())); var dailySchedule = new com.serotonin.bacnet4j.type.constructed.DailySchedule( new com.serotonin.bacnet4j.type.constructed.SequenceOf( createTimeValue(0), createTimeValue(1), createTimeValue(2) )); schedule.putBase1(1, dailySchedule); schedule.putBase1(2, dailySchedule); schedule.putBase1(3, dailySchedule); schedule.putBase1(4, dailySchedule); schedule.putBase1(5, dailySchedule); schedule.putBase1(6, dailySchedule); schedule.putBase1(7, dailySchedule); //Create the write request... See com.serotonin.bacnet4j.type.enumerated.ObjectType for object types var objectIdentifier = new com.serotonin.bacnet4j.type.primitive.ObjectIdentifier(com.serotonin.bacnet4j.type.enumerated.ObjectType.schedule, 1); //See com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier for property identifiers, // See com.serotonin.bacnet4j.obj.ObjectProperties for a correlation between object types and some possible properties they may have var propertyIdentifier = com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier.weeklySchedule; var writeRequest = new com.serotonin.bacnet4j.service.confirmed.WritePropertyRequest(objectIdentifier, propertyIdentifier, null, schedule, new com.serotonin.bacnet4j.type.primitive.UnsignedInteger(16)); //Send the request var remoteDevice = localDevice.getRemoteDeviceBlocking(86003); try { localDevice.send(remoteDevice, writeRequest); } finally { com.serotonin.ma.bacnet.device.LocalDeviceFactory.releaseLocalDevice(localDevice, listener); }
-
Thank you, @phildunlap for the response. I forwarded the info to our in-house developers and we'll get back to you with more questions later.
-
I don't think that the sample API post I provided (and have since edited out) did what I said it did. It probably just err'ed because the endpoint had changed into a bulk operations endpoint rather than a specific endpoint for a single property write. So, here's a request that will work with the post endpoint to set out a weekly schedule to schedule object 1 on device 86003. It's a simple schedule, with the value being false from 8 am to 6 pm each day, and true otherwise,
{"requests":[{ "body":{ "type": "WRITE_PROPERTIES", "devices": [ { "remoteDeviceNumber": 86003, "objects": [{ "oid": { "javaType": "com.serotonin.bacnet4j.type.primitive.ObjectIdentifier", "objectType": { "javaType": "com.serotonin.bacnet4j.type.enumerated.ObjectType", "value": "schedule" }, "instanceNumber": 1 }, "properties": [{ "javaType": "com.serotonin.bacnet4j.type.constructed.PropertyValue", "propertyIdentifier": { "javaType": "com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier", "value": "weekly-schedule" }, "value": { "javaType": "com.serotonin.bacnet4j.type.constructed.BACnetArray", "values": [{ "javaType": "com.serotonin.bacnet4j.type.constructed.DailySchedule", "daySchedule": { "javaType": "com.serotonin.bacnet4j.type.constructed.SequenceOf", "values": [{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 0, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 8, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": false } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 18, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } }] } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.DailySchedule", "daySchedule": { "javaType": "com.serotonin.bacnet4j.type.constructed.SequenceOf", "values": [{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 0, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 8, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": false } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 18, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } }] } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.DailySchedule", "daySchedule": { "javaType": "com.serotonin.bacnet4j.type.constructed.SequenceOf", "values": [{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 0, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 8, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": false } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 18, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } }] } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.DailySchedule", "daySchedule": { "javaType": "com.serotonin.bacnet4j.type.constructed.SequenceOf", "values": [{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 0, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 8, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": false } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 18, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } }] } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.DailySchedule", "daySchedule": { "javaType": "com.serotonin.bacnet4j.type.constructed.SequenceOf", "values": [{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 0, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 8, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": false } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 18, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } }] } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.DailySchedule", "daySchedule": { "javaType": "com.serotonin.bacnet4j.type.constructed.SequenceOf", "values": [{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 0, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 8, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": false } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 18, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } }] } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.DailySchedule", "daySchedule": { "javaType": "com.serotonin.bacnet4j.type.constructed.SequenceOf", "values": [{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 0, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 8, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": false } },{ "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "time": { "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "hour": 18, "minute": 0, "second": 0, "hundredth": 0 }, "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Boolean", "value": true } }] } }] } }] }] } ], "config": { "type": "IP", "localBindAddress": "0.0.0.0", "broadcastAddress": "255.255.255.255", "subnet": 24, "port": 47808, "thisStation": 0, "retryCount": 1, "deviceId": 0, "deviceName": "My Mango Automation", "localNetworkNumber": 0, "timeout": 6000, "segTimeout": 5000, "segWindow": 5, "retries": 2, "description": "I/P 0.0.0.0:47808" }, "remoteInstanceTimeout": 10000 } }]}
-
Here's an example POST to set the exception schedule attribute of the schedule to refer to a calendar object in the same device, then a schedule for days that calendar applies to,
{ "requests": [ { "body": { "type": "WRITE_PROPERTIES", "config": { "subnet": 24, "thisStation": 0, "description": "I/P 0.0.0.0:47808", "segTimeout": 5000, "deviceName": "My Mango Automation", "segWindow": 5, "localBindAddress": "0.0.0.0", "retries": 2, "broadcastAddress": "255.255.255.255", "localNetworkNumber": 0, "deviceId": 0, "timeout": 6000, "retryCount": 1, "type": "IP", "port": 47808 }, "devices": [ { "remoteDeviceNumber": 86003, "objects": [ { "oid": { "javaType": "com.serotonin.bacnet4j.type.primitive.ObjectIdentifier", "instanceNumber": 1, "objectType": { "javaType": "com.serotonin.bacnet4j.type.enumerated.ObjectType", "value": "schedule" }, "uninitialized": false }, "properties": [ { "javaType": "com.serotonin.bacnet4j.type.constructed.PropertyValue", "propertyArrayIndex": null, "propertyIdentifier": { "javaType": "com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier", "value": "exception-schedule" }, "value": { "javaType": "com.serotonin.bacnet4j.type.constructed.SequenceOf", "count": 1, "values": [ { "javaType": "com.serotonin.bacnet4j.type.constructed.SpecialEvent", "calendarReference": { "javaType": "com.serotonin.bacnet4j.type.primitive.ObjectIdentifier", "instanceNumber": 1, "objectType": { "javaType": "com.serotonin.bacnet4j.type.enumerated.ObjectType", "value": "calendar" }, "uninitialized": false }, "eventPriority": { "javaType": "com.serotonin.bacnet4j.type.primitive.UnsignedInteger", "value": 0 }, "timeValues": { "javaType": "com.serotonin.bacnet4j.type.constructed.SequenceOf", "count": 1, "values": [ { "javaType": "com.serotonin.bacnet4j.type.constructed.TimeValue", "value": { "javaType": "com.serotonin.bacnet4j.type.primitive.Enumerated", "value": "1" }, "time": { "secondUnspecified": false, "hundredth": 0, "hour": 0, "fullySpecified": true, "minuteUnspecified": false, "javaType": "com.serotonin.bacnet4j.type.primitive.Time", "second": 0, "hourUnspecified": false, "hundredthUnspecified": false, "minute": 0, "hundredthInDay": 0 } } ] } } ] }, "priority": null } ] } ] } ], "remoteInstanceTimeout": 10000 }, "error": null } ] }
I pulled the "objects" portion of the message out of a read of the existing exception schedule in this instance, then modified the timeValues array, so there may be extra keys in the message copied over from the read I made:
{"requests":[{ "body":{ "type": "READ_PROPERTIES", "devices": [ { "remoteDeviceNumber": 86003, "objects": [{ "oid": { "javaType": "com.serotonin.bacnet4j.type.primitive.ObjectIdentifier", "objectType": { "javaType": "com.serotonin.bacnet4j.type.enumerated.ObjectType", "value": "schedule" }, "instanceNumber": 1 }, "properties": [{ "javaType": "com.serotonin.bacnet4j.type.constructed.PropertyReference", "propertyIdentifier": { "javaType": "com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier", "value": "exception-schedule" } }] }] }], "config": { "type": "IP", "localBindAddress": "0.0.0.0", "broadcastAddress": "255.255.255.255", "subnet": 24, "port": 47808, "thisStation": 0, "retryCount": 1, "deviceId": 0, "deviceName": "My Mango Automation", "localNetworkNumber": 0, "timeout": 6000, "segTimeout": 5000, "segWindow": 5, "retries": 2, "description": "I/P 0.0.0.0:47808" }, "remoteInstanceTimeout": 10000 } }]}
-
Someone recently inquired about how they could use this thread if their goal was to give the user the ability to easily create and send a BACnet schedule. This post provides a means of converting an advanced scheduler schedule into a BACnet schedule via a script like,
//Lightly tested var schedule = JSON.parse(scheduleJson.value).schedule; var scheduleToSend = new com.serotonin.bacnet4j.type.constructed.BACnetArray(7, new com.serotonin.bacnet4j.type.constructed.DailySchedule( new com.serotonin.bacnet4j.type.constructed.SequenceOf())); function convertToDailySchedule(timeStrings) { var times = []; var active; if(timeStrings.length > 0 && timeStrings[0] == "00:00") { times.push( new com.serotonin.bacnet4j.type.constructed.TimeValue( new com.serotonin.bacnet4j.type.primitive.Time(0, 0, 0, 0), new com.serotonin.bacnet4j.type.primitive.Double(active.value)) ); active = true; timeStrings.shift(); //remove first element } else { times.push( new com.serotonin.bacnet4j.type.constructed.TimeValue( new com.serotonin.bacnet4j.type.primitive.Time(0, 0, 0, 0), new com.serotonin.bacnet4j.type.primitive.Double(inactive.value)) ); active = false; } for(var k in timeStrings) { var timeString = timeStrings[k]; times.push( new com.serotonin.bacnet4j.type.constructed.TimeValue( convertTimeStringToTime(timeString), active ? new com.serotonin.bacnet4j.type.primitive.Double(inactive.value) : new com.serotonin.bacnet4j.type.primitive.Double(active.value)) ); active = !active; } return new com.serotonin.bacnet4j.type.constructed.SequenceOf(times); } function convertTimeStringToTime(timeString) { var parts = timeString.split(":"); return new com.serotonin.bacnet4j.type.primitive.Time(parseInt(parts[0]), parseInt(parts[1]), 0, 0); } for(var d=0; d<7; d+=1) { //0-6 if(d < schedule.length) scheduleToSend.putBase1(d+1, convertToDailySchedule( schedule[d] )); else scheduleToSend.putBase1(d+1, convertToDailySchedule( [] )); } print(scheduleToSend);
the
active
andinactive
values are gotten from numeric context points. If you wanted more than two values, you could encode a list into an alphanumeric point and have the script work with that. ThescheduleJson
is from an SQL data source doing a row-based:select xid, defaultSchedule from advancedSchedules
Here's the JSON from my testing. I didn't actually set the schedule out to a weekly schedule on a BACnet device, though. Should work the same as the previous example.
{ "advancedSchedules": [ { "xid": "ADVSCH_1", "defaultSchedule": { "dailySchedules": [ { "changes": [ "05:20", "15:40" ] }, { "changes": [ "05:20", "15:40", "16:50", "22:40" ] }, { "changes": [ "05:20", "15:40", "16:50", "22:40" ] }, { "changes": [ "05:20", "15:40", "16:50", "22:40" ] }, { "changes": [ "05:20", "15:40", "16:50", "22:40" ] }, { "changes": [ "05:20", "15:40", "16:50", "22:40" ] }, { "changes": [ "05:20", "15:40" ] } ], "offsetCount": 24 }, "readPermission": "", "name": "bacnet", "alarmLevel": "DO_NOT_LOG", "errorAlarmLevel": "DO_NOT_LOG", "user": "admin", "editPermission": "", "enabled": false, "exceptions": [] } ], "dataSources":[ { "xid":"DS_f580c6c5-af80-45d6-b06b-ad6daf54a027", "name":"Values To Send BACnet", "enabled":true, "type":"VIRTUAL", "alarmLevels":{ "POLL_ABORTED":"URGENT" }, "purgeType":"YEARS", "updatePeriodType":"MINUTES", "polling":false, "updatePeriods":5, "editPermission":"", "purgeOverride":false, "purgePeriod":1 }, { "xid":"DS_e05d8adf-e887-4822-94f1-fe4c51187576", "name":"ScheduleSelector", "enabled":false, "type":"SQL", "alarmLevels":{ "POLL_ABORTED":"URGENT", "STATEMENT_EXCEPTION":"URGENT", "DATA_SOURCE_EXCEPTION":"URGENT" }, "purgeType":"YEARS", "updatePeriodType":"MINUTES", "connectionUrl":"jdbc:h2:C:\\\\IA\\\\Mangoes\\\\enterprise-m2m2-core-3.5.0-2\\\\databases\/mah2", "driverClassname":"org.h2.Driver", "password":"", "rowBasedQuery":true, "selectStatement":"select xid, defaultSchedule from advancedSchedules", "updatePeriods":5, "username":"", "editPermission":"", "purgeOverride":false, "purgePeriod":1 }, { "xid":"DS_dcc24ccc-988c-41ba-a2a0-07478f6b3817", "name":"Send Bacnet Schedules", "enabled":false, "type":"META", "alarmLevels":{ "SCRIPT_ERROR":"URGENT", "CONTEXT_POINT_DISABLED":"URGENT", "RESULT_TYPE_ERROR":"URGENT" }, "purgeType":"YEARS", "editPermission":"", "purgeOverride":false, "purgePeriod":1 } ], "dataPoints":[ { "xid":"DP_9baad447-7fca-415e-bd52-671f09b66f6a", "name":"Send Schedule 1", "enabled":false, "loggingType":"ON_CHANGE", "intervalLoggingPeriodType":"MINUTES", "intervalLoggingType":"INSTANT", "purgeType":"YEARS", "pointLocator":{ "dataType":"BINARY", "updateEvent":"NONE", "contextUpdateEvent":"CONTEXT_CHANGE", "context":[ { "varName":"scheduleJson", "dataPointXid":"DP_200a62c6-3788-445d-ad71-52c443328447", "updateContext":true }, { "varName":"active", "dataPointXid":"DP_ff4a9197-c12d-466e-a725-f739b31e594f", "updateContext":false }, { "varName":"inactive", "dataPointXid":"DP_9bb7dff1-9482-4053-90e7-5e8fe7b688e4", "updateContext":false } ], "logLevel":"NONE", "variableName":"my", "executionDelaySeconds":0, "logCount":5, "logSize":1.0, "script":"\/\/Lightly tested\nvar schedule = JSON.parse(scheduleJson.value).schedule;\nvar scheduleToSend = new com.serotonin.bacnet4j.type.constructed.BACnetArray(7, \n new com.serotonin.bacnet4j.type.constructed.DailySchedule(\n new com.serotonin.bacnet4j.type.constructed.SequenceOf()));\n \n \nfunction convertToDailySchedule(timeStrings) {\n var times = [];\n var active;\n if(timeStrings.length > 0 && timeStrings[0] == \"00:00\") {\n times.push(\n new com.serotonin.bacnet4j.type.constructed.TimeValue(\n new com.serotonin.bacnet4j.type.primitive.Time(0, 0, 0, 0),\n new com.serotonin.bacnet4j.type.primitive.Double(active.value))\n );\n active = true;\n timeStrings.shift(); //remove first element\n } else {\n times.push(\n new com.serotonin.bacnet4j.type.constructed.TimeValue(\n new com.serotonin.bacnet4j.type.primitive.Time(0, 0, 0, 0),\n new com.serotonin.bacnet4j.type.primitive.Double(inactive.value))\n );\n active = false;\n }\n \n for(var k in timeStrings) {\n var timeString = timeStrings[k];\n times.push(\n new com.serotonin.bacnet4j.type.constructed.TimeValue(\n convertTimeStringToTime(timeString),\n active ? \n new com.serotonin.bacnet4j.type.primitive.Double(inactive.value) :\n new com.serotonin.bacnet4j.type.primitive.Double(active.value))\n );\n active = !active;\n }\n \n return new com.serotonin.bacnet4j.type.constructed.SequenceOf(times);\n}\n\nfunction convertTimeStringToTime(timeString) {\n var parts = timeString.split(\":\");\n return new com.serotonin.bacnet4j.type.primitive.Time(parseInt(parts[0]), parseInt(parts[1]), 0, 0);\n}\n \nfor(var d=0; d<7; d+=1) { \/\/0-6\n if(d < schedule.length)\n scheduleToSend.putBase1(d+1, convertToDailySchedule( schedule[d] ));\n else\n scheduleToSend.putBase1(d+1, convertToDailySchedule( [] ));\n}\n\nprint(scheduleToSend);", "scriptPermissions":{ "customPermissions":"", "dataPointReadPermissions":"superadmin,reallycool", "dataPointSetPermissions":"superadmin,reallycool", "dataSourcePermissions":"superadmin,reallycool" }, "settable":false, "updateCronPattern":"" }, "eventDetectors":[ ], "plotType":"STEP", "rollup":"NONE", "unit":"", "templateXid":"Binary_Default", "simplifyType":"NONE", "chartColour":"", "chartRenderer":{ "type":"TABLE", "limit":10 }, "dataSourceXid":"DS_dcc24ccc-988c-41ba-a2a0-07478f6b3817", "defaultCacheSize":1, "deviceName":"Send Bacnet Schedules", "discardExtremeValues":false, "discardHighLimit":1.7976931348623157E308, "discardLowLimit":-1.7976931348623157E308, "intervalLoggingPeriod":15, "intervalLoggingSampleWindowSize":0, "overrideIntervalLoggingSamples":false, "preventSetExtremeValues":false, "purgeOverride":false, "purgePeriod":1, "readPermission":"", "setExtremeHighLimit":1.7976931348623157E308, "setExtremeLowLimit":-1.7976931348623157E308, "setPermission":"", "tags":{ }, "textRenderer":{ "type":"BINARY", "oneColour":"black", "oneLabel":"one", "zeroColour":"blue", "zeroLabel":"zero" }, "tolerance":0.0 }, { "xid":"DP_ff4a9197-c12d-466e-a725-f739b31e594f", "name":"Active Value", "enabled":true, "loggingType":"ALL", "intervalLoggingPeriodType":"MINUTES", "intervalLoggingType":"AVERAGE", "purgeType":"YEARS", "pointLocator":{ "dataType":"NUMERIC", "changeType":{ "type":"NO_CHANGE", "startValue":"10" }, "settable":true }, "eventDetectors":[ ], "plotType":"SPLINE", "rollup":"NONE", "unit":"", "templateXid":"Numeric_Default", "simplifyType":"NONE", "chartColour":"", "chartRenderer":{ "type":"IMAGE", "timePeriodType":"DAYS", "numberOfPeriods":1 }, "dataSourceXid":"DS_f580c6c5-af80-45d6-b06b-ad6daf54a027", "defaultCacheSize":1, "deviceName":"Values To Send BACnet", "discardExtremeValues":false, "discardHighLimit":1.7976931348623157E308, "discardLowLimit":-1.7976931348623157E308, "intervalLoggingPeriod":1, "intervalLoggingSampleWindowSize":0, "overrideIntervalLoggingSamples":false, "preventSetExtremeValues":false, "purgeOverride":false, "purgePeriod":1, "readPermission":"", "setExtremeHighLimit":1.7976931348623157E308, "setExtremeLowLimit":-1.7976931348623157E308, "setPermission":"", "tags":{ }, "textRenderer":{ "type":"ANALOG", "useUnitAsSuffix":true, "unit":"", "renderedUnit":"", "format":"0.00" }, "tolerance":0.0 }, { "xid":"DP_9bb7dff1-9482-4053-90e7-5e8fe7b688e4", "name":"Inactive Value", "enabled":true, "loggingType":"ALL", "intervalLoggingPeriodType":"MINUTES", "intervalLoggingType":"AVERAGE", "purgeType":"YEARS", "pointLocator":{ "dataType":"NUMERIC", "changeType":{ "type":"NO_CHANGE", "startValue":"20" }, "settable":true }, "eventDetectors":[ ], "plotType":"SPLINE", "rollup":"NONE", "unit":"", "templateXid":"Numeric_Default", "simplifyType":"NONE", "chartColour":"", "chartRenderer":{ "type":"IMAGE", "timePeriodType":"DAYS", "numberOfPeriods":1 }, "dataSourceXid":"DS_f580c6c5-af80-45d6-b06b-ad6daf54a027", "defaultCacheSize":1, "deviceName":"Values To Send BACnet", "discardExtremeValues":false, "discardHighLimit":1.7976931348623157E308, "discardLowLimit":-1.7976931348623157E308, "intervalLoggingPeriod":1, "intervalLoggingSampleWindowSize":0, "overrideIntervalLoggingSamples":false, "preventSetExtremeValues":false, "purgeOverride":false, "purgePeriod":1, "readPermission":"", "setExtremeHighLimit":1.7976931348623157E308, "setExtremeLowLimit":-1.7976931348623157E308, "setPermission":"", "tags":{ }, "textRenderer":{ "type":"ANALOG", "useUnitAsSuffix":true, "unit":"", "renderedUnit":"", "format":"0.00" }, "tolerance":0.0 }, { "xid":"DP_200a62c6-3788-445d-ad71-52c443328447", "name":"BNS_1", "enabled":true, "loggingType":"ON_CHANGE", "intervalLoggingPeriodType":"MINUTES", "intervalLoggingType":"INSTANT", "purgeType":"YEARS", "pointLocator":{ "dataType":"ALPHANUMERIC", "parameters":[ ], "dateParameterFormat":"yyyy-MM-dd'T'HH:mm:ss", "fieldName":"ADVSCH_1", "tableModifier":false, "timeOverrideName":"", "updateStatement":"" }, "eventDetectors":[ ], "plotType":"STEP", "rollup":"NONE", "unit":"", "templateXid":"Alphanumeric_Default", "simplifyType":"NONE", "chartColour":"", "chartRenderer":{ "type":"TABLE", "limit":10 }, "dataSourceXid":"DS_e05d8adf-e887-4822-94f1-fe4c51187576", "defaultCacheSize":1, "deviceName":"ScheduleSelector", "discardExtremeValues":false, "discardHighLimit":1.7976931348623157E308, "discardLowLimit":-1.7976931348623157E308, "intervalLoggingPeriod":15, "intervalLoggingSampleWindowSize":0, "overrideIntervalLoggingSamples":false, "preventSetExtremeValues":false, "purgeOverride":false, "purgePeriod":1, "readPermission":"", "setExtremeHighLimit":1.7976931348623157E308, "setExtremeLowLimit":-1.7976931348623157E308, "setPermission":"", "tags":{ }, "textRenderer":{ "type":"PLAIN", "useUnitAsSuffix":true, "unit":"", "renderedUnit":"", "suffix":"" }, "tolerance":0.0 } ] }
The Meta point is set up to run whenever the SQL point's value changes (when there is a new default weekly schedule set for the schedule), but would also run if one pressed refresh value (which you may wish to do if the inactive or active values change).
-
-
-