Suchinthana commited on
Commit
f7ba937
·
1 Parent(s): 6837238

Add IPv6 support and HTTP server changes

Browse files

Switch server binding and public IP detection to IPv6: BIND_IP now defaults to '::', public IP fetched from api64.ipify.org with a '::1' fallback, and IPv6 addresses are formatted with brackets for endpoints. Introduce format_host helper and use formatted endpoints for OPC UA (ENDPOINT/PUBLIC_ENDPOINT). Add IPv6HTTPServer (address_family=AF_INET6) and use it for the health HTTP server. Update printed server name and status messages to reflect IPv6. Minor refactor: import socket and adjust HTTP start message to show bracketed public host.

Files changed (1) hide show
  1. csv_opcua_server.py +26 -17
csv_opcua_server.py CHANGED
@@ -1,5 +1,6 @@
1
  import asyncio
2
  import threading
 
3
  from http.server import HTTPServer, BaseHTTPRequestHandler
4
 
5
  import pandas as pd
@@ -9,29 +10,42 @@ from asyncua import Server, ua
9
  # =========================
10
  # CONFIGURATION
11
  # =========================
12
- BIND_IP = "0.0.0.0"
13
  OPCUA_PORT = 4840
14
  HTTP_PORT = 7860
15
  CSV_FILE = "data.csv"
16
  ROW_INTERVAL = 2 # seconds
17
 
18
  # =========================
19
- # PUBLIC IP DETECTION
20
  # =========================
21
  def get_public_ip():
22
  try:
23
- return requests.get("https://ipinfo.io/ip", timeout=5).text.strip()
 
24
  except Exception:
25
- return "127.0.0.1"
26
 
27
  PUBLIC_IP = get_public_ip()
28
 
29
- ENDPOINT = f"opc.tcp://{BIND_IP}:{OPCUA_PORT}/csv-opcua-server/"
30
- PUBLIC_ENDPOINT = f"opc.tcp://{PUBLIC_IP}:{OPCUA_PORT}/csv-opcua-server/"
 
 
 
 
 
 
 
 
 
31
 
32
  # =========================
33
- # SIMPLE HTTP SERVER
34
  # =========================
 
 
 
35
  class HealthHandler(BaseHTTPRequestHandler):
36
  def do_GET(self):
37
  self.send_response(200)
@@ -43,24 +57,23 @@ class HealthHandler(BaseHTTPRequestHandler):
43
  return
44
 
45
  def start_http_server():
46
- httpd = HTTPServer((BIND_IP, HTTP_PORT), HealthHandler)
47
- print(f"HTTP server running on http://{PUBLIC_IP}:{HTTP_PORT}")
48
  httpd.serve_forever()
49
 
50
  # =========================
51
  # MAIN ASYNC OPC UA SERVER
52
  # =========================
53
  async def main():
54
- # Load CSV
55
  df = pd.read_csv(CSV_FILE)
56
  if df.empty:
57
  raise ValueError("CSV file is empty")
58
 
59
- # Create OPC UA server
60
  server = Server()
61
  await server.init()
 
62
  server.set_endpoint(ENDPOINT)
63
- server.set_server_name("Public CSV OPC UA Async Server")
64
 
65
  uri = "http://example.org/public-csv-opcua"
66
  idx = await server.register_namespace(uri)
@@ -68,7 +81,6 @@ async def main():
68
  objects = server.nodes.objects
69
  csv_obj = await objects.add_object(idx, "CSV_Data")
70
 
71
- # Create variables
72
  variables = {}
73
  for col in df.columns:
74
  var = await csv_obj.add_variable(
@@ -81,7 +93,7 @@ async def main():
81
  variables[col] = var
82
 
83
  print("====================================")
84
- print(" OPC UA SERVER RUNNING (ASYNC)")
85
  print(f" Internal bind : {ENDPOINT}")
86
  print(f" Public access : {PUBLIC_ENDPOINT}")
87
  print(f" Publishing 1 row every {ROW_INTERVAL} seconds")
@@ -107,8 +119,5 @@ async def main():
107
  # START EVERYTHING
108
  # =========================
109
  if __name__ == "__main__":
110
- # Start HTTP server in background thread
111
  threading.Thread(target=start_http_server, daemon=True).start()
112
-
113
- # Start async OPC UA server
114
  asyncio.run(main())
 
1
  import asyncio
2
  import threading
3
+ import socket
4
  from http.server import HTTPServer, BaseHTTPRequestHandler
5
 
6
  import pandas as pd
 
10
  # =========================
11
  # CONFIGURATION
12
  # =========================
13
+ BIND_IP = "::" # IPv6 wildcard
14
  OPCUA_PORT = 4840
15
  HTTP_PORT = 7860
16
  CSV_FILE = "data.csv"
17
  ROW_INTERVAL = 2 # seconds
18
 
19
  # =========================
20
+ # PUBLIC IP DETECTION (IPv6)
21
  # =========================
22
  def get_public_ip():
23
  try:
24
+ # This returns IPv6 if available
25
+ return requests.get("https://api64.ipify.org", timeout=5).text.strip()
26
  except Exception:
27
+ return "::1"
28
 
29
  PUBLIC_IP = get_public_ip()
30
 
31
+ # Wrap IPv6 in brackets for URL usage
32
+ def format_host(ip):
33
+ if ":" in ip:
34
+ return f"[{ip}]"
35
+ return ip
36
+
37
+ FORMATTED_BIND = format_host(BIND_IP)
38
+ FORMATTED_PUBLIC = format_host(PUBLIC_IP)
39
+
40
+ ENDPOINT = f"opc.tcp://{FORMATTED_BIND}:{OPCUA_PORT}/csv-opcua-server/"
41
+ PUBLIC_ENDPOINT = f"opc.tcp://{FORMATTED_PUBLIC}:{OPCUA_PORT}/csv-opcua-server/"
42
 
43
  # =========================
44
+ # IPV6 HTTP SERVER
45
  # =========================
46
+ class IPv6HTTPServer(HTTPServer):
47
+ address_family = socket.AF_INET6
48
+
49
  class HealthHandler(BaseHTTPRequestHandler):
50
  def do_GET(self):
51
  self.send_response(200)
 
57
  return
58
 
59
  def start_http_server():
60
+ httpd = IPv6HTTPServer((BIND_IP, HTTP_PORT), HealthHandler)
61
+ print(f"HTTP server running on http://{FORMATTED_PUBLIC}:{HTTP_PORT}")
62
  httpd.serve_forever()
63
 
64
  # =========================
65
  # MAIN ASYNC OPC UA SERVER
66
  # =========================
67
  async def main():
 
68
  df = pd.read_csv(CSV_FILE)
69
  if df.empty:
70
  raise ValueError("CSV file is empty")
71
 
 
72
  server = Server()
73
  await server.init()
74
+
75
  server.set_endpoint(ENDPOINT)
76
+ server.set_server_name("IPv6 CSV OPC UA Async Server")
77
 
78
  uri = "http://example.org/public-csv-opcua"
79
  idx = await server.register_namespace(uri)
 
81
  objects = server.nodes.objects
82
  csv_obj = await objects.add_object(idx, "CSV_Data")
83
 
 
84
  variables = {}
85
  for col in df.columns:
86
  var = await csv_obj.add_variable(
 
93
  variables[col] = var
94
 
95
  print("====================================")
96
+ print(" OPC UA SERVER RUNNING (IPv6)")
97
  print(f" Internal bind : {ENDPOINT}")
98
  print(f" Public access : {PUBLIC_ENDPOINT}")
99
  print(f" Publishing 1 row every {ROW_INTERVAL} seconds")
 
119
  # START EVERYTHING
120
  # =========================
121
  if __name__ == "__main__":
 
122
  threading.Thread(target=start_http_server, daemon=True).start()
 
 
123
  asyncio.run(main())