init from existing

This commit is contained in:
2025-07-24 16:59:52 +00:00
commit 71a97fc226
2 changed files with 369 additions and 0 deletions

263
ch10ConsumeStream.py Normal file
View File

@@ -0,0 +1,263 @@
from ast import Continue
import socket
import sys
import platform
import binascii
import datetime
import csv
from queue import Queue
import threading
import time
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
class CH10Packet:
def __init__(self, packetData):
offset = 0;
self.msgFormat = packetData[offset] & 0x0F
self.msgType = (packetData[offset] >> 4) & 0x0F
offset += 1
self.msgSeqNo = (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 3
self.uSync = (packetData[offset+1] << 8) | (packetData[offset])
offset += 2
self.channelID = (packetData[offset+1] << 8) | (packetData[offset])
offset += 2
self.pktLen = (packetData[offset+3] << 24) | (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 4
self.dataLen = (packetData[offset+3] << 24) | (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 4
self.dataTypeVer = (packetData[offset])
offset += 1
self.seqNumber = (packetData[offset])
offset += 1
self.pktFlags = (packetData[offset])
offset += 1
self.dataType = (packetData[offset])
self.bIncludesSecondaryTimeHeader = False
if (self.pktFlags / 128.0 >= 1.0):
self.bIncludesSecondaryTimeHeader = True
if self.dataType != 0X21:
return
if self.dataType == 0x00 or self.dataType == 0x01:
return
offset += 1
self.aubyRelTime = (packetData[offset+5] << 40) | (packetData[offset+4] << 32) | (packetData[offset+3] << 24) | (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 6
self.checksum = (packetData[offset+1] << 8) | (packetData[offset])
offset += 2
if(self.bIncludesSecondaryTimeHeader):
self.secondaryTimeNs = (packetData[offset+3] << 24) | (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 4
self.secondaryTimeSec = (packetData[offset+3] << 24) | (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 4
offset += 2 #rsv
self.checksumSecondary = (packetData[offset+1] << 8) | (packetData[offset])
offset += 2
self.Ch10AnalogMode = packetData[offset] & 0x03
self.Ch10AnalogLength = (packetData[offset] >> 2) & 0x3F
offset += 1
self.Ch10AnalogSubChannelID = (packetData[offset])
offset += 1
self.Ch10AnalogSubChannelCount = (packetData[offset])
offset += 1
self.Ch10AnalogFactor = packetData[offset] & 0x0F
self.Ch10AnalogSAME = (packetData[offset] >> 4) & 0x0F
offset += 1
self.bIsTSRAIR = False
if(self.Ch10AnalogSubChannelCount==18):
self.bIsTSRAIR = True
self.sampleData = list()
self.sampleCount = ((self.dataLen - 4) / self.Ch10AnalogSubChannelCount)/2.0
i = 1
while i <= self.sampleCount:
thisSample = list()
ii = 1
if(self.bIncludesSecondaryTimeHeader):
val = float(self.secondaryTimeSec) + (float(self.secondaryTimeNs)/1000000000.0) + (i/8000.0)
thisSample.append(val)
# datetime.datetime.utcfromtimestamp(self.secondaryTimeSec)
# .strftime('%Y-%m-%d %H:%M:%S') + f':{self.secondaryTimeNs}')
else:
thisSample.append(self.aubyRelTime)
while ii <= self.Ch10AnalogSubChannelCount:
thisSample.append(toSigned16(self.bIsTSRAIR,(packetData[offset+1] << 8) | (packetData[offset])))
offset+=2
ii += 1
self.sampleData.append(thisSample)
i += 1
class CH10TMATPacket:
def __init__(self, packetData):
offset = 0;
self.Version = packetData[offset] & 0xFF
if self.Version != 0x11:
return
offset += 1
self.SetupRecordConfigurationChange = (packetData[offset]) & 0x01
self.Format = (packetData[offset] & 0x02) >> 1
offset = 40
self.tmats = packetData[offset:len(packetData)+1].decode("utf-8")
multicast_group = '239.1.2.10'
interface_ip = '192.168.4.199'
multicast_port_range = [8400]
fig, ax = plt.subplots()
line, = ax.plot([], []) # Empty line object for updating data
lines = [line]
data_queue = Queue()
plotwidth = 50000
xdata = []
ydata = []
def toSigned16(bIsTSRAIR, n):
if bIsTSRAIR:
n = n & 0xffff
return (n ^ 0x8000) - 0x8000
else:
return n - 0x8000
def create_socket(interface_ip, multicast_port, multicast_group):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
# linux binds to multicast address, windows to interface address
ip_bind = interface_ip if platform.system() == "Windows" else multicast_group
sock.bind((ip_bind, multicast_port))
# socket.IPPROTO_IP works on Linux and Windows
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(interface_ip))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(multicast_group) + socket.inet_aton(interface_ip))
return sock
def initPlot():
global xdata
global ydata
ax.set_xlim(0, plotwidth)
ax.set_ylim(-32767, 32767)
line.set_data([], [])
line.set_linewidth(1)
ax.autoscale(axis='y')
xdata = [i * 1.0 for i in range(plotwidth)]
ydata = [0.0 for i in range(plotwidth)]
return line,
def animatePlot(frame):
global xdata
global ydata
items = []
while data_queue.qsize() > 0:
items.append(data_queue.get_nowait())
times = [np.floor(r[0]*1000) / 1000 for r in items]
xdata.extend(times)
xdata = xdata[0-plotwidth:]
new = [r[1] for r in items]
ydata.extend(new)
ydata = ydata[0-plotwidth:]
ax.set_xlim(min(xdata),max(xdata))
# ax.set_autoscalex_on(True)
line.set_data(xdata, ydata)
return line,
def read_packets():
read_list = []
for multicast_port in multicast_port_range:
read_list.append(create_socket(interface_ip, multicast_port, multicast_group))
bDisplayPacketMetadata = False
bDisplayPacketData = False
bDisplayPacketTmats = True
while True:
for sock in read_list:
#print(f'Reading --- {sock.getsockname()[1]}')
data, srcAddress = sock.recvfrom(1500)
ch10packet = CH10Packet(data)
# tmatsPacket = CH10TMATPacket(data)
#print(f'Received packet of {len(data)} bytes from {srcAddress[0]}:{sock.getsockname()[1]}')
if ch10packet.dataType == 0X21:
for i in ch10packet.sampleData:
data_queue.put(i)
if bDisplayPacketData:
my_array = np.array(ch10packet.sampleData)
hexdata = binascii.hexlify(my_array, " ", 2)
#hexdata = ''.join(['{:02x} '.format(b) for b in ch10packet.sampleData])
print('Data = %s' % hexdata)
if bDisplayPacketMetadata:
print(f'msgFormat: {ch10packet.msgFormat}')
print(f'msgType: {ch10packet.msgType}')
print(f'msgSeqNo: {ch10packet.msgSeqNo}')
print(f'uSync: {ch10packet.uSync}')
print(f'channelID: {ch10packet.channelID}')
print(f'pktLen: {ch10packet.pktLen}')
print(f'dataLen: {ch10packet.dataLen}')
print(f'dataTypeVer: {ch10packet.dataTypeVer}')
print(f'seqNumber: {ch10packet.seqNumber}')
print(f'pktFlags: {ch10packet.pktFlags}')
print(f'dataType: {ch10packet.dataType}')
print(f'aubyRelTime: {ch10packet.aubyRelTime}')
print(f'checksum: {ch10packet.checksum}')
if ch10packet.bIncludesSecondaryTimeHeader:
print(f'secondaryTimeNs: {ch10packet.secondaryTimeNs}')
print(f'secondaryTimeSec: {ch10packet.secondaryTimeSec}')
print('UTC Time:',datetime.datetime.utcfromtimestamp(ch10packet.secondaryTimeSec).strftime('%Y-%m-%d %H:%M:%S'), f':{ch10packet.secondaryTimeNs}')
print(f'Ch10AnalogMode: {ch10packet.Ch10AnalogMode}')
print(f'Ch10AnalogLength: {ch10packet.Ch10AnalogLength}')
print(f'Ch10AnalogSubChannelID: {ch10packet.Ch10AnalogSubChannelID}')
print(f'Ch10AnalogSubChannelCount: {ch10packet.Ch10AnalogSubChannelCount}')
print(f'Ch10AnalogFactor: {ch10packet.Ch10AnalogFactor}')
print(f'Ch10AnalogSAME: {ch10packet.Ch10AnalogSAME}')
print(f'Channel 1: {toSigned16(ch10packet.bIsTSRAIR,ch10packet.sampleData[0][1])}')
# with open(f'{srcAddress[0]}.{sock.getsockname()[1]}.{epochTimeNow}.csv', 'a', newline='') as csvfile:
# wr = csv.writer(csvfile, quoting=csv.QUOTE_ALL)
# for sample in ch10packet.sampleData:
# wr.writerow(sample)
def main():
epochTimeNow = (datetime.datetime.now(datetime.timezone.utc) - datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc)).total_seconds()
consumer_thread = threading.Thread(target=read_packets)
consumer_thread.daemon = True
consumer_thread.start()
time.sleep(0.5)
ani = animation.FuncAnimation(
fig, animatePlot,
init_func=initPlot,
interval=20,
# blit=True,
cache_frame_data=False
)
plt.show()
# input('Press enter to exit')
if __name__ == '__main__':
main()

106
chapter10.py Normal file
View File

@@ -0,0 +1,106 @@
class CH10Packet:
def __init__(self, packetData):
offset = 0;
self.msgFormat = packetData[offset] & 0x0F
self.msgType = (packetData[offset] >> 4) & 0x0F
offset += 1
self.msgSeqNo = (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 3
self.uSync = (packetData[offset+1] << 8) | (packetData[offset])
offset += 2
self.channelID = (packetData[offset+1] << 8) | (packetData[offset])
offset += 2
self.pktLen = (packetData[offset+3] << 24) | (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 4
self.dataLen = (packetData[offset+3] << 24) | (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 4
self.dataTypeVer = (packetData[offset])
offset += 1
self.seqNumber = (packetData[offset])
offset += 1
self.pktFlags = (packetData[offset])
offset += 1
self.dataType = (packetData[offset])
self.bIncludesSecondaryTimeHeader = False
if (self.pktFlags / 128.0 >= 1.0):
self.bIncludesSecondaryTimeHeader = True
if self.dataType != 0X21:
return
if self.dataType == 0x00 or self.dataType == 0x01:
return
offset += 1
self.aubyRelTime = (packetData[offset+5] << 40) | (packetData[offset+4] << 32) | (packetData[offset+3] << 24) | (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 6
self.checksum = (packetData[offset+1] << 8) | (packetData[offset])
offset += 2
if(self.bIncludesSecondaryTimeHeader):
self.secondaryTimeNs = (packetData[offset+3] << 24) | (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 4
self.secondaryTimeSec = (packetData[offset+3] << 24) | (packetData[offset+2] << 16) | (packetData[offset+1] << 8) | (packetData[offset])
offset += 4
offset += 2 #rsv
self.checksumSecondary = (packetData[offset+1] << 8) | (packetData[offset])
offset += 2
self.Ch10AnalogMode = packetData[offset] & 0x03
self.Ch10AnalogLength = (packetData[offset] >> 2) & 0x3F
offset += 1
self.Ch10AnalogSubChannelID = (packetData[offset])
offset += 1
self.Ch10AnalogSubChannelCount = (packetData[offset])
offset += 1
self.Ch10AnalogFactor = packetData[offset] & 0x0F
self.Ch10AnalogSAME = (packetData[offset] >> 4) & 0x0F
offset += 1
self.bIsTSRAIR = False
if(self.Ch10AnalogSubChannelCount==18):
self.bIsTSRAIR = True
self.sampleData = list()
self.sampleCount = ((self.dataLen - 4) / self.Ch10AnalogSubChannelCount)/2.0
i = 1
while i <= self.sampleCount:
thisSample = list()
ii = 1
if(self.bIncludesSecondaryTimeHeader):
val = float(self.secondaryTimeSec) + (float(self.secondaryTimeNs)/1000000000.0) + (i/8000.0)
thisSample.append(val)
# datetime.datetime.utcfromtimestamp(self.secondaryTimeSec)
# .strftime('%Y-%m-%d %H:%M:%S') + f':{self.secondaryTimeNs}')
else:
thisSample.append(self.aubyRelTime)
while ii <= self.Ch10AnalogSubChannelCount:
thisSample.append(toSigned16(self.bIsTSRAIR,(packetData[offset+1] << 8) | (packetData[offset])))
offset+=2
ii += 1
self.sampleData.append(thisSample)
i += 1
class CH10TMATPacket:
def __init__(self, packetData):
offset = 0;
self.Version = packetData[offset] & 0xFF
if self.Version != 0x11:
return
offset += 1
self.SetupRecordConfigurationChange = (packetData[offset]) & 0x01
self.Format = (packetData[offset] & 0x02) >> 1
offset = 40
self.tmats = packetData[offset:len(packetData)+1].decode("utf-8")
def toSigned16(bIsTSRAIR, n):
if bIsTSRAIR:
n = n & 0xffff
return (n ^ 0x8000) - 0x8000
else:
return n - 0x8000