Business background

Recently received A demand in WeChat public interface design an independent interface, interface with A motor and A motor back into A, B, B motor back four buttons, click on the corresponding button, the cloud platform to send different code to local motor controller, control motor to perform different actions, motor local controller have GPRS network function. The server and the motor local controller (client) are connected by TCP protocol, and the client sends heartbeat packets to the server to maintain a long connection. The client responds to the code instructions sent by the server each time. The main realization principle is that the front-end accesses the interface of the background to transmit data. Background using socket and GPRS module into the link, exposed an IP+PORT to GPRS access, the implementation of logic is relatively simple. However, there are some thorny problems in the development, and the following are summarized.

Technology stack

The front part of the main technology stack adopts VUE and weUI, and the background adopts koA framework of Node. The front page is directly written in KOA, because the page is relatively simple, so there is no separation before and after.

The implementation process

1. Front end

 <div class="wrap">
     <button @click="goA('A1')" class="weui-btn" v-bind:class="{ 'weui-btn_loading': btnStatus.cur == 'A1'&&btnStatus.status==0, 'weui-btn_primary': btnStatus.cur == 'A1'&&btnStatus.status==1, 'weui-btn_plain-primary': btnStatus.cur ! = 'A1' }"< span style = "box-sizing: border-box! Important; word-wrap: break-word! Important;"btnStatus.cur == 'A1'&&btnStatus.status==0" class="weui-loading"></i></button>

     <button @click="backA('A0')" class="weui-btn" v-bind:class="{ 'weui-btn_loading': btnStatus.cur == 'A0'&&btnStatus.status==0, 'weui-btn_primary': btnStatus.cur == 'A0'&&btnStatus.status==1, 'weui-btn_plain-default': btnStatus.cur ! = 'A0' }">A back < I v-show="btnStatus.cur == 'A0'&&btnStatus.status==0" class="weui-loading"></i></button>

     <button @click="goB('B1')" class="weui-btn" v-bind:class="{ 'weui-btn_loading': btnStatus.cur == 'B1'&&btnStatus.status==0, 'weui-btn_primary': btnStatus.cur == 'B1'&&btnStatus.status==1, 'weui-btn_plain-primary': btnStatus.cur ! = 'B1' }"< span style = "box-sizing: border-box! Important; word-wrap: break-word! Important;"btnStatus.cur == 'B1'&&btnStatus.status==0" class="weui-loading"></i></button>
     
     <button @click="backB('B0')" class="weui-btn" v-bind:class="{ 'weui-btn_loading': btnStatus.cur == 'B0'&&btnStatus.status==0, 'weui-btn_primary': btnStatus.cur == 'B0'&&btnStatus.status==1, 'weui-btn_plain-default': btnStatus.cur ! = 'B0' }">B back < I v-show="btnStatus.cur == 'B0'&&btnStatus.status==0" class="weui-loading"></i></button>
   </div>
Copy the code

Send data to the background part of the code is as follows:

// A goA (id){axios.post('/djxt/move', { id })
            .then( (response)=> {
              console.log(response);
              if( response.data.success ){
                this.alertDialog.content = 'Operation successful';
                this.alertDialog.status = true;
              }else{
                this.alertDialog.content = 'Operation failed';
                this.alertDialog.status = true;
              }
            })
            .catch( (error)=> {
              console.log(error);
                this.alertDialog.content = 'Operation failed';
                this.alertDialog.status = true;
            });
          }
Copy the code

2. Background implementation

Due to the use of node technology stack, the original use is the scoket. IO to carry out the scoket link, but in the later development found that this method needs an event to trigger the submission of data, in the client also need to have an event to monitor, not suitable for communication with GPRS, finally abandoned helplessly. The NET module of Node is used for communication. The module can send data of bound ports as long as it calls WRITE (data). It’s relatively simple. Check out nodejs.org/dist/latest… If you can’t read English, you can find a Chinese version. Net connection can be written in WWW file or app.js file, see your needs. Interface 127.0.0.1:3004 is exposed in this project with the following code:

//socket
var net = require('net'); // Server IP var HOST ='127.0.0.1'; Var PORT = 3004; // Create a TCP server instance and call listen to start listening on the specified port. // The callback passed into Net.createserver () will act as a handler for the "Connection" event. The socket object received by this callback is a unique net.createserver (function(sock) {// Global sock, which can be called elsewhere. Sock = sock // get a socket connection, output the client to console.log('CONNECTED: ' +
    sock.remoteAddress + ':'+ sock.remotePort); // Add one for the socket instance"data"Event handler function that receives client data sock.on('data'.function(data) {
    console.log('DATA ' + sock.remoteAddress + ':'+ data); ECHO // sock.write(// sock.write(' '+ data ); }); // Add one for the socket instance"close"Event handler sock.on('close'.function(data) {
    console.log('CLOSED: ' +
        sock.remoteAddress + ' ' + sock.remotePort);
});

}).listen(PORT, HOST);

Copy the code

In the code, HOST is the IP you need to expose to the GPRS module, and PORT is the PORT. When net.createserver creates a service, it calls back sock that can be used to do some listening, such as the client returning data sock.on(‘data’, function(data) {}). A problem encountered in the development process is that the HOST can be accessed locally with 127.0.0.1, but after the cloud service, the port can not be accessed. The solution is to change HOST to the internal IP address of your own server. Global. Sock = sock This is mainly to expose global sock, can be called elsewhere, be sure to expose.

The server side processes the data sent from the front end and sends it to the GPRS module. In this project, the route for front-end access is/MOVE. After entering this route, judge and then forward the value to GPRS. The key point here is to use sock.write() of global Sock to send it to the client. The following code

Router.post ('/move', async (ctx, next) => {
  let params = ctx.request.body;
  
  // console.log('CTX. State:, global.sock)
  // console.log('ctx.state2222: ', sock)
  console.log('Front-end interface:', params)
  if( !sock ){
    ctx.body = {
      data: params,
      success: false,
      msg: 'Socket does not exist'}}else{
    sock.write( params.id );

    ctx.body = {
      data: params,
      success: true,
      msg: ' '}}})Copy the code

The complete code is available on Github. Github.com/bayi-lzp/no…