import math
import threading
import time
import spvirit
class SensorBackend:
def __init__(self):
self._values = {
"SENSOR:TEMP": 22.0,
"SENSOR:PRESSURE": 1.0,
"SENSOR:FLOW": 5.0,
}
self._lock = threading.Lock()
self._notifier = None
self._stop = threading.Event()
self._thread = threading.Thread(target=self._loop, daemon=True)
def on_start(self, notifier):
self._notifier = notifier
self._thread.start()
def claim(self, name):
if name in self._values:
return spvirit.PvInfo.nt_scalar("double") return None
def get(self, name):
with self._lock:
if name in self._values:
return spvirit.NtScalar(self._values[name])
return None
def put(self, name, value):
raise RuntimeError(f"'{name}' is read-only")
def names(self):
return list(self._values.keys())
def _loop(self):
t = 0.0
while not self._stop.is_set():
new = {
"SENSOR:TEMP": 22.0 + 2.0 * math.sin(t),
"SENSOR:PRESSURE": 1.0 + 0.1 * math.sin(t * 1.7),
"SENSOR:FLOW": 5.0 + 1.0 * math.sin(t * 0.4),
}
with self._lock:
self._values.update(new)
if self._notifier is not None:
for name, v in new.items():
self._notifier.notify(name, spvirit.NtScalar(v))
t += 0.2
time.sleep(0.5)
def main():
server = (
spvirit.ServerBuilder()
.add_source("sensors", 10, SensorBackend())
.build()
)
server.start_background()
print("Sensor source server on port 5075.")
print(" PVs: SENSOR:TEMP, SENSOR:PRESSURE, SENSOR:FLOW (updated every 0.5s)")
print(" Try: spmonitor SENSOR:TEMP")
try:
while True:
time.sleep(3600)
except KeyboardInterrupt:
print("\nbye.")
if __name__ == "__main__":
main()