数据情况
通过sid字段挂接,35个一组
数据流结构 CSV
IOT点位数据
点位数据提前发布为FeatureServer要素服务
注意关联字段类型与GeoEvent定义一致
创建GeoEvent定义(数据结构)
根据数据流结构决定,注意关联字段与GeoEvent定义一致
创建TCP接收器
推送csv数据
import socket
import time# 指定服务器的IP地址和端口号
server_ip = '192.168.1.142'
server_port = 5565# 创建一个socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 连接到服务器
client_socket.connect((server_ip, server_port))while True:# 打开CSV文件with open('stationRealTime.csv', 'r') as file:# 跳过标题行next(file)# 初始化行计数器line_count = 0# 初始化数据缓存data_buffer = ''for line in file:# 将当前行添加到数据缓存data_buffer += "STA," + lineline_count += 1# 每35行或文件末尾,发送数据if line_count == 35:# 发送数据client_socket.sendall(data_buffer.encode('utf-8'))print(data_buffer)# 清空数据缓存和行计数器data_buffer = ''line_count = 0# 等待1秒``time.sleep(1)# 发送剩余的数据(如果有)if data_buffer:client_socket.sendall(data_buffer.encode('utf-8'))print(data_buffer)time.sleep(1)client_socket.close()
创建StreamService输出器
选择关联要素
创建GeoEvent定义
前端页面构建
主要实现:
- class-breaks 根据data分级渲染
- popupTemplate 点击弹窗显示 sid 、data
- boatLabelClass 标注 data 值
<html lang="zh-cn"><head><meta charset="utf-8" /><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /><title>StreamLayer | Sample </title><style>html,body,#viewDiv {height: 100%;width: 100%;margin: 0;padding: 0;}#streamLayerDiv {padding: 10px;background-color: #f5f5f5;}</style><link rel="stylesheet" href="https://js.arcgis.com/4.30/esri/themes/light/main.css" /><script src="https://js.arcgis.com/4.30/"></script><script>require(["esri/Map","esri/views/MapView","esri/layers/StreamLayer","esri/geometry/Polygon","esri/Graphic","esri/widgets/LayerList","esri/core/reactiveUtils","esri/layers/support/LabelClass","esri/widgets/Legend"], (Map, MapView, StreamLayer, Polygon, Graphic, LayerList, reactiveUtils, LabelClass, Legend) => {let streamLayer, streamLayerView;const svcUrl = "https://ip142.gsgz.com:6443/geoscene/rest/services/station-stream-out/StreamServer";const map = new Map({basemap: "gray-vector"});const view = new MapView({container: "viewDiv",map: map,center: [113, 23],zoom: 9});view.ui.add(new LayerList({ view }), "bottom-left");let renderer2 = {type: "class-breaks",field: "data",classBreakInfos: [{minValue: 100,maxValue: 300,symbol: {type: "simple-marker",size: 10,color: "red",outline: {color: [0, 255, 0],width: 1}}},{minValue: 300,maxValue: 600,symbol: {type: "simple-marker",size: 10,color: "yellow",outline: {color: [0, 255, 0],width: 1}}},{minValue: 600,maxValue: 1000,symbol: {type: "simple-marker",size: 10,color: "green",outline: {color: [0, 255, 0],width: 1}}}],defaultSymbol :{type: "simple-marker",size: 10,color: "blue",}}const boatLabelClass = new LabelClass({labelExpressionInfo: { expression: "$feature.data" },symbol: {type: "text", // autocasts as new LabelSymbol3D()symbolLayers: [{type: "text", // autocasts as new TextSymbol3DLayer()material: { color: [ 49,163,84 ] },size: 12 // points}]}});// Construct Stream Layerconst layer = new StreamLayer({url: svcUrl,purgeOptions: {displayCount: 10000},popupTemplate: {title: "{status}",content: "{sid}, {data}"},renderer: renderer2,labelingInfo : [boatLabelClass],timeInfo: {trackIdField: "sid"}});map.add(layer);const legend = new Legend({view: view});view.ui.add(legend, "top-left");});</script>
</head><body><div id="viewDiv"></div>
</body></html>
验证
StreamServer订阅
StreamServer流服务不带位置信息
前端页面
值动态变化,实现数据流绑定点位