first commit for the sender side
This commit is contained in:
commit
17715b22ad
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
.env
|
||||||
|
venv/
|
||||||
0
__init__.py
Normal file
0
__init__.py
Normal file
80
client.py
Normal file
80
client.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# sender/client.py — TCP socket client, connects to receiver and sends data
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from config import HOST, PORT, SEND_INTERVAL, ACK_BYTE, RECONNECT_DELAY, BUFFER_SIZE
|
||||||
|
from generator import generate_data
|
||||||
|
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--id", required=True, help="Device ID")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
DEVICE_ID = args.id
|
||||||
|
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format="[SENDER] %(asctime)s — %(message)s",
|
||||||
|
datefmt="%H:%M:%S"
|
||||||
|
)
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def connect_to_server() -> socket.socket:
|
||||||
|
"""Keep trying to connect until server is available."""
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
client.connect((HOST, PORT))
|
||||||
|
log.info(f"Connected to server at {HOST}:{PORT}")
|
||||||
|
return client
|
||||||
|
except ConnectionRefusedError:
|
||||||
|
log.warning(f"Server not available. Retrying in {RECONNECT_DELAY}s...")
|
||||||
|
time.sleep(RECONNECT_DELAY)
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
log.info(f"Sender starting with DEVICE_ID={DEVICE_ID}...")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
client = connect_to_server()
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
# 1. Generate data string with unique ID
|
||||||
|
data = generate_data(DEVICE_ID)
|
||||||
|
display = data.replace('\0', '\\0')
|
||||||
|
log.info(f"Sending → {display}")
|
||||||
|
|
||||||
|
# 2. Send encoded bytes
|
||||||
|
client.sendall(data.encode('utf-8'))
|
||||||
|
|
||||||
|
# 3. Wait for ACK
|
||||||
|
try:
|
||||||
|
client.settimeout(5.0)
|
||||||
|
ack = client.recv(BUFFER_SIZE)
|
||||||
|
if ack == ACK_BYTE:
|
||||||
|
log.info("ACK received")
|
||||||
|
else:
|
||||||
|
log.warning(f"Unexpected response: {ack}")
|
||||||
|
except socket.timeout:
|
||||||
|
log.error("ACK timeout — server may be down")
|
||||||
|
break
|
||||||
|
|
||||||
|
# 4. Wait before next send
|
||||||
|
time.sleep(SEND_INTERVAL)
|
||||||
|
|
||||||
|
except (ConnectionResetError, BrokenPipeError, OSError) as e:
|
||||||
|
log.error(f"Connection lost: {e}. Reconnecting...")
|
||||||
|
finally:
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run()
|
||||||
8
config.py
Normal file
8
config.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# config.py — shared settings for sender and receiver
|
||||||
|
|
||||||
|
HOST = "127.0.0.1"
|
||||||
|
PORT = 3000
|
||||||
|
SEND_INTERVAL = 5 # seconds between each data send
|
||||||
|
BUFFER_SIZE = 4096
|
||||||
|
ACK_BYTE = b'\x06' # standard ACK control character
|
||||||
|
RECONNECT_DELAY = 3 # seconds before sender retries connection
|
||||||
39
generator.py
Normal file
39
generator.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# sender/generator.py — generates realistic solar sensor data strings
|
||||||
|
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
DOOR_STATES = ["OPEN", "CLOSE"]
|
||||||
|
|
||||||
|
|
||||||
|
def generate_data(device_id: str) -> str:
|
||||||
|
|
||||||
|
ts = int(time.time())
|
||||||
|
sv = round(random.uniform(40.0, 55.0), 1)
|
||||||
|
si = round(random.uniform(0.0, 40.0), 1)
|
||||||
|
sp = random.randint(0, 2200)
|
||||||
|
bv = round(random.uniform(44.0, 58.0), 2)
|
||||||
|
bcur = round(random.uniform(-30.0, 30.0), 1)
|
||||||
|
bsoc = random.randint(0, 100)
|
||||||
|
bsoh = random.randint(80, 100)
|
||||||
|
bt = round(random.uniform(10.0, 50.0), 1)
|
||||||
|
at = round(random.uniform(15.0, 45.0), 1)
|
||||||
|
door = random.choice(DOOR_STATES)
|
||||||
|
|
||||||
|
message = (
|
||||||
|
f"ID={device_id},"
|
||||||
|
f"TS={ts},"
|
||||||
|
f"SV={sv},"
|
||||||
|
f"SI={si},"
|
||||||
|
f"SP={sp},"
|
||||||
|
f"BV={bv},"
|
||||||
|
f"BCUR={bcur},"
|
||||||
|
f"BSOC={bsoc},"
|
||||||
|
f"BSOH={bsoh},"
|
||||||
|
f"BT={bt},"
|
||||||
|
f"AT={at},"
|
||||||
|
f"DOOR={door}"
|
||||||
|
f"\0"
|
||||||
|
)
|
||||||
|
return message
|
||||||
Loading…
x
Reference in New Issue
Block a user