mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 01:18:36 +02:00
Bindings: Add LiveData and LiveDataMessage support in Python bindings
This commit is contained in:
committed by
Kyle Schwarz
parent
000036f745
commit
977677e3af
@@ -29,7 +29,7 @@ int main() {
|
||||
}
|
||||
std::cout << "OK" << std::endl;
|
||||
|
||||
// Create a subscription message for the GPS signals
|
||||
// Create a subscription message for the GPS signals and TIME_SINCE_MSG
|
||||
std::cout << "\tSending a live data subscribe command... ";
|
||||
auto msg = std::make_shared<icsneo::LiveDataCommandMessage>();
|
||||
msg->appendSignalArg(icsneo::LiveDataValueType::GPS_LATITUDE);
|
||||
@@ -37,6 +37,7 @@ int main() {
|
||||
msg->appendSignalArg(icsneo::LiveDataValueType::GPS_ACCURACY);
|
||||
msg->appendSignalArg(icsneo::LiveDataValueType::DAQ_ENABLE);
|
||||
msg->appendSignalArg(icsneo::LiveDataValueType::MANUAL_TRIGGER);
|
||||
msg->appendSignalArg(icsneo::LiveDataValueType::TIME_SINCE_MSG);
|
||||
msg->cmd = icsneo::LiveDataCommand::SUBSCRIBE;
|
||||
msg->handle = icsneo::LiveDataUtil::getNewHandle();
|
||||
msg->updatePeriod = std::chrono::milliseconds(100);
|
||||
@@ -44,6 +45,9 @@ int main() {
|
||||
// Transmit the subscription message
|
||||
ret = device->subscribeLiveData(msg);
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
if (!ret) {
|
||||
std::cout << "\t\tError: " << icsneo::GetLastError() << std::endl;
|
||||
}
|
||||
|
||||
// Register a handler that uses the data after it arrives every ~100ms
|
||||
std::cout << "\tStreaming messages for 3 seconds... " << std::endl << std::endl;
|
||||
@@ -53,19 +57,21 @@ int main() {
|
||||
switch(ldMsg->cmd) {
|
||||
case icsneo::LiveDataCommand::STATUS: {
|
||||
auto msg2 = std::dynamic_pointer_cast<icsneo::LiveDataStatusMessage>(message);
|
||||
std::cout << "[Handle] " << ldMsg->handle << std::endl;
|
||||
std::cout << "[Requested Command] " << msg2->requestedCommand << std::endl;
|
||||
std::cout << "[Status] " << msg2->status << std::endl << std::endl;
|
||||
std::cout << "[STATUS Message]" << std::endl;
|
||||
std::cout << " Handle: " << ldMsg->handle << std::endl;
|
||||
std::cout << " Requested Command: " << msg2->requestedCommand << std::endl;
|
||||
std::cout << " Status: " << msg2->status << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
case icsneo::LiveDataCommand::RESPONSE: {
|
||||
auto valueMsg = std::dynamic_pointer_cast<icsneo::LiveDataValueMessage>(message);
|
||||
if((valueMsg->handle == msg->handle) && (valueMsg->values.size() == msg->args.size()))
|
||||
{
|
||||
std::cout << "[Handle] " << msg->handle << std::endl;
|
||||
std::cout << "[Values] " << valueMsg->numArgs << std::endl;
|
||||
std::cout << "[Response Message]" << std::endl;
|
||||
std::cout << " Handle: " << msg->handle << std::endl;
|
||||
std::cout << " Number of Values: " << valueMsg->numArgs << std::endl;
|
||||
for(uint32_t i = 0; i < valueMsg->numArgs; ++i) {
|
||||
std::cout << "[" << msg->args[i]->valueType << "] ";
|
||||
std::cout << " [" << msg->args[i]->valueType << "] ";
|
||||
auto scaledValue = icsneo::LiveDataUtil::liveDataValueToDouble(*valueMsg->values[i]);
|
||||
std::cout << scaledValue << std::endl;
|
||||
}
|
||||
@@ -86,22 +92,33 @@ int main() {
|
||||
setValMsg->cmd = icsneo::LiveDataCommand::SET_VALUE;
|
||||
setValMsg->handle = msg->handle;
|
||||
// Convert the value format
|
||||
icsneo::LiveDataValue ldValueDAQEnable;
|
||||
icsneo::LiveDataValue ldValueManTrig;
|
||||
if (!icsneo::LiveDataUtil::liveDataDoubleToValue(val / 3, ldValueDAQEnable) ||
|
||||
!icsneo::LiveDataUtil::liveDataDoubleToValue(val, ldValueManTrig)) {
|
||||
auto ldValueDAQEnable = icsneo::LiveDataUtil::liveDataDoubleToValue(val / 3);
|
||||
auto ldValueManTrig = icsneo::LiveDataUtil::liveDataDoubleToValue(val);
|
||||
auto ldValueTimeSinceMsg = icsneo::LiveDataUtil::liveDataDoubleToValue(val);
|
||||
if (!ldValueDAQEnable || !ldValueManTrig || !ldValueTimeSinceMsg) {
|
||||
std::cout << "\tError: Failed to convert values" << std::endl;
|
||||
break;
|
||||
}
|
||||
setValMsg->appendSetValue(icsneo::LiveDataValueType::DAQ_ENABLE, ldValueDAQEnable);
|
||||
setValMsg->appendSetValue(icsneo::LiveDataValueType::MANUAL_TRIGGER, ldValueManTrig);
|
||||
device->setValueLiveData(setValMsg);
|
||||
setValMsg->appendSetValue(icsneo::LiveDataValueType::DAQ_ENABLE, *ldValueDAQEnable);
|
||||
setValMsg->appendSetValue(icsneo::LiveDataValueType::MANUAL_TRIGGER, *ldValueManTrig);
|
||||
setValMsg->appendSetValue(icsneo::LiveDataValueType::TIME_SINCE_MSG, *ldValueTimeSinceMsg);
|
||||
|
||||
std::cout << "\tSetting values: DAQ_ENABLE=" << (val / 3)
|
||||
<< ", MANUAL_TRIGGER=" << val
|
||||
<< ", TIME_SINCE_MSG=" << val << std::endl;
|
||||
|
||||
if (!device->setValueLiveData(setValMsg)) {
|
||||
std::cout << "\tError setting values: " << icsneo::GetLastError() << std::endl;
|
||||
}
|
||||
++val;
|
||||
// Run handler for three seconds to observe the signal data
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||
}
|
||||
// Unsubscribe from the GPS signals and run handler for one more second
|
||||
// Unsubscription only requires a valid in-use handle, in this case from our previous subscription
|
||||
std::cout << "\tUnsubscribing... ";
|
||||
ret = device->unsubscribeLiveData(msg->handle);
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
// The handler should no longer print values
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
device->removeMessageCallback(handler);
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
"""
|
||||
LiveData subscription and monitoring example using icsneopy library.
|
||||
|
||||
"""
|
||||
|
||||
import icsneopy
|
||||
import time
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
def livedata_example():
|
||||
"""Subscribe to and monitor LiveData signals."""
|
||||
devices = icsneopy.find_all_devices()
|
||||
if not devices:
|
||||
raise RuntimeError("No devices found")
|
||||
|
||||
device = devices[0]
|
||||
print(f"Using device: {device}")
|
||||
|
||||
try:
|
||||
if not device.open():
|
||||
raise RuntimeError("Failed to open device")
|
||||
|
||||
if not device.go_online():
|
||||
raise RuntimeError("Failed to go online")
|
||||
|
||||
device.enable_message_polling()
|
||||
|
||||
# Create subscription message
|
||||
msg = icsneopy.LiveDataCommandMessage()
|
||||
msg.handle = icsneopy.get_new_handle()
|
||||
msg.cmd = icsneopy.LiveDataCommand.SUBSCRIBE
|
||||
msg.update_period = timedelta(milliseconds=500)
|
||||
msg.expiration_time = timedelta(milliseconds=0)
|
||||
|
||||
# Subscribe to various LiveData signals
|
||||
msg.append_signal_arg(icsneopy.LiveDataValueType.GPS_LATITUDE)
|
||||
msg.append_signal_arg(icsneopy.LiveDataValueType.GPS_LONGITUDE)
|
||||
msg.append_signal_arg(icsneopy.LiveDataValueType.GPS_ACCURACY)
|
||||
msg.append_signal_arg(icsneopy.LiveDataValueType.DAQ_ENABLE)
|
||||
msg.append_signal_arg(icsneopy.LiveDataValueType.MANUAL_TRIGGER)
|
||||
msg.append_signal_arg(icsneopy.LiveDataValueType.TIME_SINCE_MSG)
|
||||
|
||||
print("\nSubscribing to LiveData signals...")
|
||||
if not device.subscribe_live_data(msg):
|
||||
raise RuntimeError(f"Subscription failed: {icsneopy.get_last_error()}")
|
||||
|
||||
print("Subscription successful")
|
||||
print("\nMonitoring LiveData for 5 seconds...")
|
||||
|
||||
response_count = 0
|
||||
start_time = time.time()
|
||||
|
||||
while time.time() - start_time < 5:
|
||||
result = device.get_messages()
|
||||
messages = result[0] if isinstance(result, tuple) else result
|
||||
|
||||
for m in messages:
|
||||
if isinstance(m, icsneopy.LiveDataStatusMessage):
|
||||
if m.handle == msg.handle:
|
||||
print(f"\n[Status] Command: {m.requested_command}, Status: {m.status}")
|
||||
|
||||
elif isinstance(m, icsneopy.LiveDataValueMessage):
|
||||
if m.handle == msg.handle:
|
||||
response_count += 1
|
||||
print(f"\n[Response #{response_count}]")
|
||||
signal_names = ["GPS_LAT", "GPS_LON", "GPS_ACC",
|
||||
"DAQ_EN", "MAN_TRIG", "TIME_SINCE"]
|
||||
for idx, val in enumerate(m.values):
|
||||
value = icsneopy.livedata_value_to_double(val)
|
||||
name = signal_names[idx] if idx < len(signal_names) else f"Signal_{idx}"
|
||||
print(f" {name:12s}: {value:10.2f}")
|
||||
|
||||
time.sleep(0.1)
|
||||
|
||||
print(f"\nReceived {response_count} response messages")
|
||||
|
||||
# Demonstrate setting values
|
||||
print("\nSetting custom values...")
|
||||
set_msg = icsneopy.LiveDataSetValueMessage()
|
||||
set_msg.handle = icsneopy.get_new_handle()
|
||||
set_msg.cmd = icsneopy.LiveDataCommand.SET_VALUE
|
||||
|
||||
# Set DAQ_ENABLE
|
||||
value = icsneopy.livedata_double_to_value(1.0)
|
||||
if value:
|
||||
set_msg.append_set_value(icsneopy.LiveDataValueType.DAQ_ENABLE, value)
|
||||
|
||||
# Set MANUAL_TRIGGER
|
||||
value = icsneopy.livedata_double_to_value(1.0)
|
||||
if value:
|
||||
set_msg.append_set_value(icsneopy.LiveDataValueType.MANUAL_TRIGGER, value)
|
||||
|
||||
if device.set_value_live_data(set_msg):
|
||||
print("Values set successfully")
|
||||
time.sleep(0.5)
|
||||
|
||||
# Check the results
|
||||
result = device.get_messages()
|
||||
messages = result[0] if isinstance(result, tuple) else result
|
||||
for m in messages:
|
||||
if isinstance(m, icsneopy.LiveDataStatusMessage):
|
||||
if m.handle == set_msg.handle:
|
||||
print(f" Set status: {m.status}")
|
||||
|
||||
# Keep device awake by resetting TIME_SINCE_MSG
|
||||
print("\nResetting TIME_SINCE_MSG to keep device awake...")
|
||||
reset_msg = icsneopy.LiveDataSetValueMessage()
|
||||
reset_msg.handle = icsneopy.get_new_handle()
|
||||
reset_msg.cmd = icsneopy.LiveDataCommand.SET_VALUE
|
||||
|
||||
value = icsneopy.livedata_double_to_value(0.0)
|
||||
if value:
|
||||
reset_msg.append_set_value(icsneopy.LiveDataValueType.TIME_SINCE_MSG, value)
|
||||
if device.set_value_live_data(reset_msg):
|
||||
print("TIME_SINCE_MSG reset to 0")
|
||||
|
||||
# Unsubscribe
|
||||
print("\nUnsubscribing...")
|
||||
if device.unsubscribe_live_data(msg.handle):
|
||||
print("Unsubscribed successfully")
|
||||
|
||||
finally:
|
||||
device.close()
|
||||
print("\nDevice closed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
livedata_example()
|
||||
|
||||
Reference in New Issue
Block a user