Skip to content

Instantly share code, notes, and snippets.

@bbartling
Last active March 15, 2024 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bbartling/6a771fb2fcb4a9491db481d7edcb7eec to your computer and use it in GitHub Desktop.
Save bbartling/6a771fb2fcb4a9491db481d7edcb7eec to your computer and use it in GitHub Desktop.
concept idea rest API for global share values in typical BAS contracting... Usually the boiler plant controller ALWAYS has the outside air temperature sensor hardwired and its ALWAYS needed to share that sensor value to other devices like air handling units that need that value to execute sequencing.
import requests
import random
import time
BASE_URL = "http://localhost:8000"
def simulate_sensor_reading(sensor_name):
# This function simulates reading a sensor by generating a random value.
# Replace this logic with actual sensor reading if integrating with real sensors or systems.
if sensor_name == "outside_air_temperature":
return random.uniform(30, 50) # Simulate to sometimes trigger the alarm
elif sensor_name == "hot_water_supply_temperature":
return random.uniform(90, 120)
else: # Zone temperature sensors
return random.uniform(65, 75)
def check_conditions_and_notify(outside_air_temp, hot_water_supply_temp, zone_temps):
critical_low_temp = 40.0
critical_low_hot_water_temp = 100.0
zone_critical_low = 60.0
zone_critical_high = 85.0
if (
outside_air_temp < critical_low_temp
and hot_water_supply_temp < critical_low_hot_water_temp
):
print(
f"Critical alarm: Outside air temp is {outside_air_temp}F, hot water supply temp is {hot_water_supply_temp}F."
)
for zone, temp in enumerate(zone_temps, start=1):
if temp < zone_critical_low:
print(f"Critical low temperature alarm in zone {zone}: {temp}F.")
elif temp > zone_critical_high:
print(f"Critical high temperature alarm in zone {zone}: {temp}F.")
def main():
while True:
# Simulate reading from sensors
outside_air_temp = simulate_sensor_reading("outside_air_temperature")
hot_water_supply_temp = simulate_sensor_reading("hot_water_supply_temperature")
zone_temps = [
simulate_sensor_reading(f"zone_{i}_temp") for i in range(1, 6)
] # Simulating 5 zone temps
# Check and notify based on conditions
check_conditions_and_notify(outside_air_temp, hot_water_supply_temp, zone_temps)
print("Waiting for 5 minutes before the next update...")
time.sleep(300)
if __name__ == "__main__":
main()
import requests
BASE_URL = "http://localhost:8000"
def add_device(device_data):
"""Add a new BACnet device to the network."""
response = requests.post(f"{BASE_URL}/devices", json=device_data)
if response.status_code == 200:
print("Device added successfully.")
return response.json()
else:
print(f"Error adding device: {response.text}")
return None
def delete_device(device_id):
"""Delete a device from the network."""
response = requests.delete(f"{BASE_URL}/devices/{device_id}")
if response.status_code == 200:
print(f"Device {device_id} deleted successfully.")
else:
print(f"Error deleting device {device_id}: {response.text}")
def add_point_to_device(device_id, point_data):
"""Add a new point to a device."""
response = requests.post(f"{BASE_URL}/devices/{device_id}/points", json=point_data)
if response.status_code == 200:
print("Point added successfully.")
return response.json()
else:
print(f"Error adding point: {response.text}")
return None
def delete_point_from_device(device_id, point_id):
"""Delete a point from a device."""
response = requests.delete(f"{BASE_URL}/devices/{device_id}/points/{point_id}")
if response.status_code == 200:
print(f"Point {point_id} deleted successfully.")
else:
print(f"Error deleting point {point_id}: {response.text}")
def main():
# Example of adding a new device
new_device = {
"name": "Boiler Controller",
"instance_id": 1001,
"type": "boiler"
}
device = add_device(new_device)
device_id = device.get('instance_id') if device else None
if device_id:
# Add points to the device
points = [
{"name": "Outside Air Temperature", "type": "analog-input", "alarms": "enabled", "trends": "enabled"},
{"name": "Hot Water Supply Temperature", "type": "analog-value", "alarms": "enabled", "trends": "enabled"}
]
for point in points:
add_point_to_device(device_id, point)
# Example to delete a point, assuming point_id is known or retrieved from previous responses
delete_point_from_device(device_id, 1) # Simulated point_id
# Delete the device
delete_device(device_id)
if __name__ == "__main__":
main()
// node javascript
const axios = require('axios');
const BASE_URL = 'http://localhost:8000';
async function readPresentValue(device_instance, object_identifier) {
try {
const url = `${BASE_URL}/${device_instance}/${object_identifier}`;
const response = await axios.get(url);
return response.data['present-value'];
} catch (error) {
console.error(`Error reading value: ${error}`);
return null;
}
}
async function writePresentValue(device_instance, object_identifier, value) {
try {
const url = `${BASE_URL}/write/${device_instance}/${object_identifier}`;
const response = await axios.post(url, { value: value });
console.log('Successfully wrote value.');
} catch (error) {
console.error(`Error writing value: ${error}`);
}
}
async function main() {
while (true) {
const boiler_device_instance = 201201;
const boiler_object_identifier = 'analog-input,2';
const outside_air_temp = await readPresentValue(boiler_device_instance, boiler_object_identifier);
if (outside_air_temp !== null) {
console.log(`Outside Air Temperature: ${outside_air_temp}°C`);
const devices_to_update = [
[301101, 'analog-value,1'],
[301102, 'analog-value,1'],
[401201, 'analog-value,2'],
];
for (const [device_instance, object_identifier] of devices_to_update) {
await writePresentValue(device_instance, object_identifier, outside_air_temp);
}
}
console.log('Waiting for 5 minutes before the next update...');
await new Promise(resolve => setTimeout(resolve, 300000)); // Sleep for 5 minutes
}
}
main();
-- Lua example
local http = require("socket.http")
local ltn12 = require("ltn12")
local json = require("dkjson")
local BASE_URL = "http://localhost:8000"
function readPresentValue(device_instance, object_identifier)
local url = string.format("%s/%s/%s", BASE_URL, device_instance, object_identifier:gsub(",", "%%2C"))
local response_body = {}
local res, code = http.request{
url = url,
sink = ltn12.sink.table(response_body)
}
if code == 200 then
local decoded_response = json.decode(table.concat(response_body))
return decoded_response["present-value"]
else
print("Error reading value: "..(res or code))
return nil
end
end
function writePresentValue(device_instance, object_identifier, value)
local url = string.format("%s/write/%s/%s", BASE_URL, device_instance, object_identifier:gsub(",", "%%2C"))
local response_body = {}
local encoded_value = json.encode({value = value})
local res, code = http.request{
method = "POST",
url = url,
source = ltn12.source.string(encoded_value),
headers = {
["content-type"] = "application/json",
["content-length"] = tostring(#encoded_value)
},
sink = ltn12.sink.table(response_body)
}
if code == 200 then
print("Successfully wrote value.")
else
print("Error writing value: "..(res or code))
end
end
function main()
while true do
local boiler_device_instance = 201201
local boiler_object_identifier = "analog-input,2"
local outside_air_temp = readPresentValue(boiler_device_instance, boiler_object_identifier)
if outside_air_temp then
print("Outside Air Temperature: "..outside_air_temp.."°C")
local devices_to_update = {
{301101, "analog-value,1"},
{301102, "analog-value,1"},
{401201, "analog-value,2"},
}
for _, device in ipairs(devices_to_update) do
writePresentValue(device[1], device[2], outside_air_temp)
end
end
print("Waiting for 5 minutes before the next update...")
socket.sleep(300) -- Sleep for 5 minutes
end
end
main()
import requests
import time
BASE_URL = "http://localhost:8000"
def read_present_value(device_instance, object_identifier):
try:
url = f"{BASE_URL}/{device_instance}/{object_identifier.replace(',', '%2C')}"
response = requests.get(url)
if response.status_code == 200:
return response.json().get("present-value", None)
else:
print(
f"Error reading value with status {response.status_code}: {response.text}"
)
return None
except requests.RequestException as e:
print(f"Request failed: {e}")
return None
def write_present_value(device_instance, object_identifier, value):
try:
url = f"{BASE_URL}/write/{device_instance}/{object_identifier.replace(',', '%2C')}"
response = requests.post(url, json={"value": value})
if response.status_code == 200:
print("Successfully wrote value.")
else:
print(
f"Error writing value with status {response.status_code}: {response.text}"
)
except requests.RequestException as e:
print(f"Request failed: {e}")
def main():
while True:
boiler_device_instance = 201201
boiler_object_identifier = "analog-input,2"
outside_air_temp = read_present_value(
boiler_device_instance, boiler_object_identifier
)
if outside_air_temp is not None:
print(f"Outside Air Temperature: {outside_air_temp}°C")
devices_to_update = [
(301101, "analog-value,1"),
(301102, "analog-value,1"),
(401201, "analog-value,2"),
]
for device_instance, object_identifier in devices_to_update:
write_present_value(device_instance, object_identifier, outside_air_temp)
print("Waiting for 5 minutes before the next update...")
time.sleep(300)
if __name__ == "__main__":
main()
use reqwest::Error;
use serde_json::Value;
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() -> Result<(), Error> {
let client = reqwest::Client::new();
let base_url = "http://localhost:8000";
loop {
let device_instance = "201201";
let object_identifier = "analog-input,2";
let read_url = format!("{}/{}/{}", base_url, device_instance, object_identifier);
match client.get(&read_url).send().await?.json::<Value>().await {
Ok(resp) => {
if let Some(present_value) = resp["present-value"].as_f64() {
println!("Outside Air Temperature: {}°C", present_value);
let devices_to_update = vec![
("301101", "analog-value,1"),
("301102", "analog-value,1"),
("401201", "analog-value,2"),
];
for (device_instance, object_identifier) in devices_to_update {
let write_url = format!("{}/write/{}/{}", base_url, device_instance, object_identifier);
// Simulate writing the value - adjust as needed for your actual API
let _ = client.post(&write_url)
.json(&serde_json::json!({ "value": present_value }))
.send().await?;
}
}
},
Err(e) => println!("Error reading value: {}", e),
}
println!("Waiting for 5 minutes before the next update...");
sleep(Duration::from_secs(300)).await;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment