Article From:https://www.cnblogs.com/iotopo/p/iotweb.html

Preface

  Industrial Internet of Things (IOT) is a very wide concept. This paper introduces a minimization platform of industrial Internet of Things (IOT) from the point of view of data visualization, from Modbus data acquisition to front-end data visualization. This is mainly about data mining based on Modbus protocol.Collection, background real-time data processing, front-end real-time data reception, and real-time visualization of front-end real-time data. The architecture of the Internet of Things platform mainly refers to the industrial Internet of Things platform of Map-and-Put-and-Things, and introduces some functions extracted from it. The front-end data visualization is adopted.HT for Web

  Because there are many contents, the implementation involves the participation of front-end engineer, back-end engineer, data acquisition engineer and other development roles, so this paper focuses on the implementation ideas and the implementation of WebSocket message push, the details of the implementation of other links will be carried out in other articles.Detailed introduction.

 

I. platform architecture of the Internet of things

  The Internet of Things (IOT) platform is mainly B/S mode. Most of the industrial IOT platforms use micro-service architecture. This paper mainly involves two micro-services: pre-data acquisition service and Web real-time message push service.

  Pre-data acquisition service is mainly used for real-time data acquisition of field equipment, instruments, meters and sensors. The IoTopo Industrial Internet of Things platform supports MQTT and cloud resolution, and cloud resolution supports Modbus protocol.

  After the real-time data is collected on the platform, it needs to be pushed to the browser for display. Web real-time message push service uses Web Socket for real-time data push, which can ensure the real-time and high efficiency of data.

 

  The front-end visualization technology uses HT for Web. HT for Web is a one-stop solution of enterprise application graphical interface based on HTML5 standard. It contains rich graphical interface development libraries such as general components, topological components and 3D rendering engine. Although HT fOrWeb is a commercial software, but its one-stop solution can greatly shorten the product development cycle, reduce research and development costs, complement our shortcomings in Web graphical interface visualization technology.

 

Two, Modbus data acquisition

ModbusIt is a serial communication protocol that was published by Modicon (now Schneider Electric) in 1979 to communicate using a programmable logic controller (PLC). Modbus has become the industry standard for communication protocols in industrial fields.And now is a common way of connection between industrial electronic devices. Modbus is more widely used than other communication protocols.

  1. Published and no copyright requirement.
  2. Easy to deploy and maintain
  3. For suppliers, there are not many restrictions on modifying mobile local bits or bytes.

ModbusAllows multiple (about 240) devices to communicate over the same network, for example, a device that measures temperature and humidity and sends the results to a computer. In data acquisition and monitoring control system (SCADA), Modbus is usually used to connect monitoring computers andRemote terminal control system (RTU).

At present, the mainstream editing languages all have Modbus development libraries, because Modbus is relatively simple, many enterprises also choose to develop and implement their own. Modbus data acquisition belongs to background communication. After data acquisition to the platform, data cleaning and pretreatment will be carried out first to filter out redundancy and redundancy.Invalid data to form real-time data. When the platform acquires real-time data, it usually does 3 tasks:

1. Push to Web front end for display

2. Store to sequential database

3. Determine whether an alarm is generated.

 

 

Three, push real-time data to Web front-end.

  Real time data push based on Web needs to be used.WebSocket,Beginners can learn from teacher Nguyen Feng. WebSocket Course。We encapsulate a set of message transfer protocols based on WebSocket, similar to a message middleware, where the front end can subscribe to real-time data. Considering the push demand of massive real-time data, the real-time data is divided into platform level, site level and device level. The front-end can subscribe to real-time data throughMessage topic rules subscribe to different levels of data. The platform side can automatically push a real-time data when receiving the subscription request. This ensures that the data visualization interface displays the correct interface the first time the subscription to real-time data is successful.

  Below is a simplified WebSocket messaging protocol client code, you can be based on some of the transformation to suit their own business scenarios.

  Message topic regular expression to match the message subject:

1 const matchWildcard = function(str, rule) {
2     return new RegExp('^' + rule.split('*').join('.*') + '$').test(str)
3 }

  WebSocket The client supports message topic subscriptions, cancels message topic subscriptions, and supports multiple subscribers for the same message topic:

  1 class WebSocketClient {
  2     constructor() {
  3         this.ws = null
  4         this.opts = {
  5             debug: false,
  6             autoReconnect: true,
  7             reconnectInterval: 10000,
  8             subscriber: {},
  9         }
 10         this.opened = false
 11     }
 12 
 13     connect() {
 14         if (!this.opened) {
 15             return
 16         }
 17 
 18         const url = 'ws://www.iotopo.com/msg/v1'
 19         console.debug('websocket connect', url)
 20 
 21         let ws = this.ws = new WebSocket(url)
 22         ws.onmessage = event => {
 23             if (this.opts.debug) {
 24                 console.log(event)
 25             }
 26             let data = JSON.parse(event.data)
 27 
 28             for (let topic in this.opts.subscriber) {
 29                 if (matchWildcard(data.topic, topic)) {
 30                     let listeners = this.opts.subscriber[topic]
 31                     if (Array.isArray(listeners)) {
 32                         listeners.forEach(cb => {
 33                             if (typeof cb === 'function') {
 34                                 cb(data.payload)
 35                             }
 36                         })
 37                     }
 38                 }
 39             }
 40         }
 41         ws.onopen = e => {
 42             if (this.opts.debug) {
 43                 console.log(e)
 44             }
 45             // Execute subscription requests 46             for (let topic in this.opts.subscriber) {
 47                 this._sendSubscribe(topic)
 48             }
 49             if (typeof this.opts.onopen === 'function') {
 50                 this.opts.onopen(e)
 51             }
 52         }
 53         ws.onclose = e => {
 54             if (this.opts.debug) {
 55                 console.log(e)
 56             }
 57             if (typeof this.opts.onclose === 'function') {
 58                 this.opts.onclose(e)
 59             }
 60             if (this.opened && this.opts.autoReconnect) {
 61                 setTimeout(() => {
 62                     this.connect()
 63                 }, this.opts.reconnectInterval)
 64             }
 65         }
 66         ws.onerror = e => {
 67             if (this.opts.debug) {
 68                 console.log(e)
 69             }
 70             if (typeof this.opts.onerror === 'function') {
 71                 this.opts.onerror(e)
 72             }
 73         }
 74     }
 75 
 76     open(opts) {
 77         if (!this.opened) {
 78             Object.assign(this.opts, opts || {})
 79             this.opened = true
 80             this.connect()
 81         }
 82     }
 83 
 84     close() {
 85         this.opened = false
 86         if (this.ws !== null) {
 87             this.ws.close()
 88         }
 89         this.ws = null
 90     }
 91 
 92     isOpened() {
 93         return this.opened
 94     }
 95 
 96     isConnected() {
 97         return this.ws !== null
 98     }
 99 
100     _sendSubscribe(topic) {
101         if (this.ws === null) {
102             return Error('websocet not opened')
103         }
104         if (typeof topic !== 'string') {
105             return Error('topic should be a string value')
106         }
107 
108         if (this.ws.readyState === WebSocket.OPEN) {
109             let msg = {
110                 type: 'subscribe',
111                 topic: topic,
112             }
113             this.ws.send(JSON.stringify(msg))
114         } else {
115             return Error('websocet not connected')
116         }
117     }
118 
119     subscribe(topic, cb) {
120         if (this.opts.debug) {
121             console.log('subscribe:', topic)
122         }
123         let listeners = this.opts.subscriber[topic]
124         if (!Array.isArray(listeners)) {
125             listeners = [
126                 cb
127             ]
128             this.opts.subscriber[topic] = listeners
129         } else {
130             listeners.push(cb)
131         }
132         this._sendSubscribe(topic)
133 
134         return { topic, cb }
135     }
136 
137     unsubscribe({topic, cb}) {
138         if (this.opts.debug) {
139             console.log('unsubscribe:', topic)
140         }
141 
142         if (this.ws === null) {
143             return Error('websocet not opened')
144         }
145 
146         if (typeof topic !== 'string') {
147             return Error('topic should be a string value')
148         }
149 
150         let listeners = this.opts.subscriber[topic]
151         if (cb) {
152             if (Array.isArray(listeners)) {
153                 let idx = listeners.indexOf(cb)
154                 if (idx >= 0) {
155                     listeners.splice(idx, 1)
156                 }
157             }
158         } else {
159             delete this.opts.subscriber[topic]
160         }
161 
162         if (Array.isArray(listeners) && listeners == 0) {
163             if (this.ws.readyState === WebSocket.OPEN) {
164                 let msg = {
165                     type: 'unsubscribe',
166                     topic: topic,
167                 }
168                 this.ws.send(JSON.stringify(msg))
169             } else {
170                 return Error('websocet not connected')
171             }
172         }
173     }
174 }

  Usage example:

 1 // Initialization client 2 const ws = new WebSocketClient()
 3 // Propose connection with WebSocket server 4 ws.open({
 5     debug: false
 6 })
 7 // Subscribe 8 ws.subscribe('/foo/bar/*', function(msg) {
 9     console.log('recv ws msg:', msg)
10 })

 

Four, data visualization interface implementation

  Based on HT for Web, a visual graphical interface conforming to HTML5 standard can be built easily and quickly, and real-time data can be subscribed through WebSocket, then the change of graphical interface can be driven. There are many ways to change the data driven graphical interface.In the way of data binding, we can refer to HT for Web.Official documents

In a later article, the author introduces a data binding method based on HT for Web implementation for separating business data from graphical data.

 

Online presentation address

Leave a Reply

Your email address will not be published. Required fields are marked *