1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import random
import struct
import socket
import time

# 设备ID列表
DEVICE_IDS = [
"333804318B10",
"3338158B14FD",
"3338978BC34C",
"333826AD44CE",
"3338CA967271",
"3338AB12D24F",
"3338C8A47C4B",
"33387AED3585",
"3338DA08B0CC",
"333825246E4A"
]

# 初始值
previous_ph_value = 7.0
previous_conductivity_value = 30.0
previous_dissolved_oxygen_value = 10.0
previous_turbidity_value = 150.0
previous_water_temperature_value = 10.0

def generate_random_data():
global previous_ph_value, previous_conductivity_value, previous_dissolved_oxygen_value, previous_turbidity_value, previous_water_temperature_value

# 固定的字段值
frame_header = b'\xFE\xDC' # 字头
fixed_value = b'\x01' # 固定值
unused_bytes = b'\x00\x00\x00\x06\x03' # 无用字节
content_length = b'\x00\x20' # 后面内容长度
signal_strength = b'\x00\x00\x00\x45' # 信号强度
error_code = b'\x00\x00\x00\x00'
version = b'\x00\x00\x00\x75' # 版本号
checksum = b'\x00' # 校验位

# 随机选择一个设备ID
device_id = random.choice(DEVICE_IDS)

# 生成符合实际水质范围的随机值并确保格式正确
ph_value = previous_ph_value + random.uniform(-0.1, 0.1)
ph_value = max(6.5, min(8.5, ph_value)) # 保证ph值在6.5到8.5之间
ph = struct.pack('>I', int(ph_value * 100))
previous_ph_value = ph_value

conductivity_value = previous_conductivity_value + random.uniform(-0.5, 0.5)
conductivity_value = max(20, min(40, conductivity_value)) # 保证电导率值在20到40之间
conductivity = struct.pack('>I', int(conductivity_value * 10))
previous_conductivity_value = conductivity_value

dissolved_oxygen_value = previous_dissolved_oxygen_value + random.uniform(-0.5, 0.5)
dissolved_oxygen_value = max(0, min(20, dissolved_oxygen_value)) # 保证溶解氧值在0到20之间
dissolved_oxygen = struct.pack('>I', int(dissolved_oxygen_value * 10))
previous_dissolved_oxygen_value = dissolved_oxygen_value

turbidity_value = previous_turbidity_value + random.uniform(-5, 5)
turbidity_value = max(0, min(300, turbidity_value)) # 保证浊度值在0到300之间
turbidity = struct.pack('>I', int(turbidity_value * 1))
previous_turbidity_value = turbidity_value

water_temperature_value = previous_water_temperature_value + random.uniform(-0.5, 0.5)
water_temperature_value = max(2, min(20, water_temperature_value)) # 保证水温值在2到20之间
water_temperature = struct.pack('>I', int(water_temperature_value * 10))
previous_water_temperature_value = water_temperature_value

# 将所有字段组合成一个完整的数据报文
data = (frame_header + fixed_value + bytes.fromhex(device_id) + unused_bytes + content_length +
ph + conductivity + dissolved_oxygen + turbidity + water_temperature +
signal_strength + error_code + version + checksum)

return data

def generate_and_send_data(server_ip, server_port):
# 生成随机数据
data = generate_random_data()

# 创建TCP套接字并连接到服务器
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:
try:
client_socket.connect((server_ip, server_port))
# 发送数据
client_socket.sendall(data)
print(f'{data.hex().upper()}')
except ConnectionRefusedError:
print("Connection refused. Make sure the server is running.")

if __name__ == "__main__":
SERVER_IP = 'ch.jitux.com' # 修改为你的服务器IP地址
SERVER_PORT = 8001 # 修改为你的服务器端口号

while True:
generate_and_send_data(SERVER_IP, SERVER_PORT)
time.sleep(5) # 每隔5秒发送一次数据

当程序运行时,会主动和服务器握手,并每5秒发送一条数据给服务器数据格式:

1
FEDC013338AB12D24F00000006030020000000000000000000000000000000000000000000000065000000000000007500

进阶版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import random
import struct
import socket
import time
from datetime import datetime

# 设备ID列表
DEVICE_IDS = [
"333804318B10",
"3338158B14FD",
"3338978BC34C",
"333826AD44CE",
"3338CA967271",
"3338AB12D24F",
"3338C8A47C4B",
"33387AED3585",
"3338DA08B0CC",
"333825246E4A"
]

# 初始值
previous_ph_value = 7.0
previous_conductivity_value = 30.0
previous_dissolved_oxygen_value = 10.0
previous_turbidity_value = 150.0
previous_water_temperature_value = 10.0

def generate_random_data():
global previous_ph_value, previous_conductivity_value, previous_dissolved_oxygen_value, previous_turbidity_value, previous_water_temperature_value

# 获取当前时间
now = datetime.now()
current_hour = now.hour
current_minute = now.minute

# 判断当前时间是否在12:00到12:10之间
if current_hour == 12 and current_minute < 10:
# 随机生成水质参数,并确保变化不大
ph_value = previous_ph_value + random.uniform(-0.1, 0.1)
ph_value = max(6.5, min(8.5, ph_value)) # 保证ph值在6.5到8.5之间
previous_ph_value = ph_value

conductivity_value = previous_conductivity_value + random.uniform(-0.5, 0.5)
conductivity_value = max(20, min(40, conductivity_value)) # 保证电导率值在20到40之间
previous_conductivity_value = conductivity_value

dissolved_oxygen_value = previous_dissolved_oxygen_value + random.uniform(-0.5, 0.5)
dissolved_oxygen_value = max(0, min(20, dissolved_oxygen_value)) # 保证溶解氧值在0到20之间
previous_dissolved_oxygen_value = dissolved_oxygen_value

turbidity_value = previous_turbidity_value + random.uniform(-5, 5)
turbidity_value = max(0, min(300, turbidity_value)) # 保证浊度值在0到300之间
previous_turbidity_value = turbidity_value

water_temperature_value = previous_water_temperature_value + random.uniform(-0.5, 0.5)
water_temperature_value = max(2, min(20, water_temperature_value)) # 保证水温值在2到20之间
previous_water_temperature_value = water_temperature_value
else:
ph_value = 0.0
conductivity_value = 0.0
dissolved_oxygen_value = 0.0
turbidity_value = 0.0
water_temperature_value = 0.0

# 将值转换为字节
ph = struct.pack('>I', int(ph_value * 100))
conductivity = struct.pack('>I', int(conductivity_value * 10))
dissolved_oxygen = struct.pack('>I', int(dissolved_oxygen_value * 10))
turbidity = struct.pack('>I', int(turbidity_value * 1))
water_temperature = struct.pack('>I', int(water_temperature_value * 10))

# 固定的字段值
frame_header = b'\xFE\xDC' # 字头
fixed_value = b'\x01' # 固定值
unused_bytes = b'\x00\x00\x00\x06\x03' # 无用字节
content_length = b'\x00\x20' # 后面内容长度
signal_strength = b'\x00\x00\x00\x55'
error_code = b'\x00\x00\x00\x00'
version = b'\x00\x00\x00\x75' # 版本号
checksum = b'\x00' # 校验位

# 随机选择一个设备ID
device_id = random.choice(DEVICE_IDS)

# 将所有字段组合成一个完整的数据报文
data = (frame_header + fixed_value + bytes.fromhex(device_id) + unused_bytes + content_length +
ph + conductivity + dissolved_oxygen + turbidity + water_temperature +
signal_strength + error_code + version + checksum)

return data

def generate_and_send_data(server_ip, server_port):
# 生成随机数据
data = generate_random_data()

# 创建TCP套接字并连接到服务器
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:
try:
client_socket.connect((server_ip, server_port))
# 发送数据
client_socket.sendall(data)
print(f'{data.hex().upper()}')
except ConnectionRefusedError:
print("Connection refused. Make sure the server is running.")

if __name__ == "__main__":
SERVER_IP = 'ch.jitux.com' # 修改为你的服务器IP地址
SERVER_PORT = 8001 # 修改为你的服务器端口号

while True:
generate_and_send_data(SERVER_IP, SERVER_PORT)
time.sleep(5) # 每隔5秒发送一次数据

当每天12点到12点10分期间进行模拟,别的时候讲发送数值0.
备注测试期间搭建接受服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# -*- coding: utf-8 -*-
import socket
import logging
import signal
import sys
from datetime import datetime

# 设置服务器地址和端口
HOST = '0.0.0.0' # 监听所有网络接口
PORT = 8001 # 使用新的端口号

# 设置日志记录
logging.basicConfig(filename='server.log', level=logging.INFO, format='%(asctime)s %(message)s')

def parse_data(data):
"""
解析接收到的数据并打印每个字段的内容
"""
if len(data) < 50: # 检查数据长度是否足够
logging.info("Received data is too short.")
return

frame_header = data[0:2].hex()
fixed_value = data[2:3].hex()
device_id = data[3:9].hex()
unused_bytes = data[9:15].hex()
content_length = int.from_bytes(data[15:17], byteorder='big')
ph = int.from_bytes(data[17:21], byteorder='big') / 100.0
conductivity = int.from_bytes(data[21:25], byteorder='big') / 100.0
dissolved_oxygen = int.from_bytes(data[25:29], byteorder='big') / 100.0
turbidity = int.from_bytes(data[29:33], byteorder='big') / 100.0
water_temperature = int.from_bytes(data[33:37], byteorder='big') / 100.0
signal_strength = int.from_bytes(data[37:41], byteorder='big')
error_code = int.from_bytes(data[41:45], byteorder='big')
version = int.from_bytes(data[45:49], byteorder='big')
checksum = data[49:50].hex()

logging.info(f"Frame Header: {frame_header}")
logging.info(f"Fixed Value: {fixed_value}")
logging.info(f"Device ID: {device_id}")
logging.info(f"Unused Bytes: {unused_bytes}")
logging.info(f"Content Length: {content_length}")
logging.info(f"PH: {ph}")
logging.info(f"Conductivity: {conductivity}")
logging.info(f"Dissolved Oxygen: {dissolved_oxygen}")
logging.info(f"Turbidity: {turbidity}")
logging.info(f"Water Temperature: {water_temperature}")
logging.info(f"Signal Strength: {signal_strength}")
logging.info(f"Error Code: {error_code}")
logging.info(f"Version: {version}")
logging.info(f"Checksum: {checksum}")

# 捕获终端信号以优雅地关闭服务器
def signal_handler(sig, frame):
print('Stopping server...')
sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

# 创建TCP套接字
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
# 绑定地址和端口
server_socket.bind((HOST, PORT))
# 开始监听连接
server_socket.listen()

logging.info(f'Server is listening on port {PORT}...')
print(f'Server is listening on port {PORT}...')

# 接受连接并处理报文
while True:
# 等待客户端连接
client_socket, client_address = server_socket.accept()
with client_socket:
logging.info(f'Connected to {client_address}')
print(f'Connected to {client_address}')
# 接收数据
data = client_socket.recv(1024)
if data:
receive_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
logging.info(f'Received raw data at {receive_time}: {data.hex()}')
print(f'Received raw data at {receive_time}: {data.hex()}')
# 解析并打印每个字段的内容
parse_data(data)
else:
logging.info('No data received.')
print('No data received.')