基於surging的木舟IOT平臺如何新增網路元件

fanly11發表於2024-08-28

一 、 概述

為了彌補程式碼的遺失,木舟IOT平臺正在加班加點進行研發,後面不只是針對於IOT裝置接入上報,告警,影片管理,組態資料視覺化大屏,後面還會有快速搭建微服務平臺,利用surging.cli工具根據資料庫表生成微服務,中間服務,能讓程式設計師快速完成BOSS交給的任務,從而在這個內卷的社會能佔有一席之地。這些都是沒有完成任務的空話,現在發此篇的目的是作者有能力開發出優秀的IOT平臺,先介紹一個比較突出的功能,就是可以基於共享或者獨立配置新增網路元件, 下面來介紹一下如何新增網路元件。

一鍵執行打包成品下載:https://pan.baidu.com/s/11hcf9ieCkJxlGrzvIuxeQA?pwd=ajsr

測試使用者:fanly

測試密碼:123456

為了讓大家節約時間,能儘快執行產品看到效果,上面有 一鍵執行打包成品可以進行下載測試執行。

二、如何測試執行

以下是目錄結構,

IDE:consul 註冊中心

kayak.client: 閘道器

kayak.server:微服務

apache-skywalking-apm:skywalking鏈路跟蹤

以上是目錄結構,大家不需要一個個執行,只需要開啟執行startup.bat,如果需要測試skywalking ,只需要apache-skywalking-apm\bin\startup.bat 檔案就可以了,以下是執行的介面

三、如何新增元件

1.新增http服務元件,

開啟平臺介面,然後點選裝置接入->網路元件,然後可以看到如下介面

再點選新增元件或者編輯元件,完成後注意啟動狀態是關閉狀態,此時並不能對於該元件功能進行訪問呼叫,只有把啟動狀態開啟,才能訪問呼叫

以上是http服務元件,啟動完成後,如果設定了webservice和swagger,你可以訪問webservice和swagger,看是否可以訪問

2.新增/編輯Tcp服務元件

當新增/編輯Tcp元件時,設定Host:127.0.0.1 ,port:248並且還有解析方式選項,選項裡面有不處理,固定長度,分隔符,自定義指令碼,下面我們就來看自定義指令碼

新增指令碼如下:

parser.Fixed(4).Handler(
                  function(buffer){
                    var buf = BytesUtils.Slice(buffer,1,4);
                    parser.Fixed(buffer.ReadableBytes).Result(buf);
             }).Handler(
                    function(buffer){parser.Fixed(8).Result(buffer);}
            ).Handler(function(buffer){
                    parser.Result('處理完成','gb2312').Complete();
                 }
             )

而基於TCP服務程式碼如下,需要繼承於TcpBehavior

    internal class TcpDeviceDataService : TcpBehavior, ITcpDeviceDataService
    {
        private readonly IDeviceProvider _deviceProvider;
        public TcpDeviceDataService(IDeviceProvider deviceProvider)
        {
            _deviceProvider = deviceProvider;
        }

        public override void Load(string clientId, NetworkProperties tcpServerProperties)
        {
            var deviceStatus = _deviceProvider.IsConnected(clientId);
            this.Parser.HandlePayload().Subscribe(async buffer => await ParserBuffer(buffer));
        }

        public override void DeviceStatusProcess(DeviceStatus status, string clientId, NetworkProperties tcpServerProperties)
        {
            //throw new NotImplementedException();
        }

        public async Task ParserBuffer(IByteBuffer buffer)
        {
            List<string> result = new List<string>();
            while (buffer.ReadableBytes > 0)
            {
                result.Add(buffer.ReadString(this.Parser.GetNextFixedRecordLength(),
                    Encoding.GetEncoding("gb2312")));
            }

            // var str= buffer.ReadString(buffer.ReadableBytes, Encoding.UTF8);

            var byteBuffer = Unpooled.Buffer();
            byteBuffer.WriteString("\r\n", Encoding.UTF8);
            byteBuffer.WriteString("處理完成", Encoding.GetEncoding("gb2312"));
            await Sender.SendAndFlushAsync(byteBuffer); 
            //  await Sender.SendAndFlushAsync("訊息已接收",Encoding.GetEncoding("gb2312"));
            this.Parser.Close();
        }

        public Task<bool> ChangeDeviceStage(string deviceId)
        {
            throw new NotImplementedException();
        }
    }

用測試Tcp除錯工具結果如下

3.新增/編輯UDP服務元件

當新增/編輯UDP元件時, 設定Host:127.0.0.1 ,port:267 並且可以是否開啟組播

而基於udp服務程式碼如下,需要繼承於UdpBehavior

  internal class UdpDeviceDataService : UdpBehavior, IUdpDeviceDataService
  {
      public Task<bool> ChangeDeviceStage(string deviceId)
      {
          throw new NotImplementedException();
      }

      public override async Task Dispatch(IEnumerable<byte> bytes)
      {
          await Sender.SendAndFlushAsync("\r\n", Encoding.UTF8);
          await Sender.SendAndFlushAsync("處理完成", Encoding.GetEncoding("gb2312"));
      }
  }

測試結果如下:

4.新增/編輯WebSocket服務元件

當新增/編輯WebSocket元件時, 設定Host:127.0.0.1 ,port:55

而基於websocket服務程式碼如下,需要繼承於WSBehavior

internal class WSDeviceDataService : WSBehavior, IWSDeviceDataService
{
    protected override void OnMessage(MessageEventArgs e)
    {
        this.Client.Value.SendTo($"send:{e.Data},\r\n reply:hello,welcome to you!",ID);
    }

    protected override void OnOpen()
    {
     
    }
}

測試結果如下:

5.新增/編輯UDP服務元件

當新增/編輯WebSocket元件時, 設定Host:127.0.0.1 ,port:345

新增greet.proto檔案,指令碼如下:

syntax = "proto3";
 
package Greet;
 
service Greeter {
  // Sends a greeting
  rpc ChangeDeviceStage (DeviceRequest) returns (DeviceReply) {}
}
 
message DeviceRequest {
  string deviceId = 1;
}
 
message  DeviceReply {
 bool message = 1;
}

然後再建立GreeterBehavior,繼承Greeter.GreeterBase, IServiceBehavior,程式碼如下

public partial class GreeterBehavior : Greeter.GreeterBase, IServiceBehavior
{
    private ServerReceivedDelegate received;
    public event ServerReceivedDelegate Received
    {
        add
        {
            if (value == null)
            {
                received += value;
            }
        }
        remove
        {
            received -= value;
        }
    }

    public string MessageId { get; } = Guid.NewGuid().ToString("N");
    public async Task Write(object result, int statusCode = 200, string exceptionMessage = "")
    {
        if (received == null)
            return;
        var message = new TransportMessage(MessageId, new ReactiveResultMessage
        {
            ExceptionMessage = exceptionMessage,
            StatusCode = statusCode,
            Result = result

        });
        await received(message);
    }

    public T CreateProxy<T>(string key) where T : class
    {
        return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>(key);
    }

    public object CreateProxy(Type type)
    {
        return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy(type);
    }

    public object CreateProxy(string key, Type type)
    {
        return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy(key, type);
    }

    public T CreateProxy<T>() where T : class
    {
        return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>();
    }

    public T GetService<T>(string key) where T : class
    {
        if (ServiceLocator.Current.IsRegisteredWithKey<T>(key))
            return ServiceLocator.GetService<T>(key);
        else
            return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>(key);
    }

    public T GetService<T>() where T : class
    {
        if (ServiceLocator.Current.IsRegistered<T>())
            return ServiceLocator.GetService<T>();
        else
            return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>();

    }

    public object GetService(Type type)
    {
        if (ServiceLocator.Current.IsRegistered(type))
            return ServiceLocator.GetService(type);
        else
            return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy(type);
    }

    public object GetService(string key, Type type)
    {
        if (ServiceLocator.Current.IsRegisteredWithKey(key, type))
            return ServiceLocator.GetService(key, type);
        else
            return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy(key, type);

    } 
    public void Publish(IntegrationEvent @event)
    {
        GetService<IEventBus>().Publish(@event);
    }

}

而基於grpc服務程式碼如下,需要繼承於剛剛建立的GreeterBehavior

    public class GrpcDeviceDataService : GreeterBehavior, IGrpcDeviceDataService
    {
        public override Task<DeviceReply> ChangeDeviceStage(DeviceRequest request, ServerCallContext context)
        {
            return Task.FromResult(new DeviceReply
            {
                Message = true
            }) ;
        }
    }

以下是測試結果:

6.新增/編輯MQTT服務元件

當新增/編輯MQTT元件時, 設定Host:127.0.0.1 ,port:425

而基於mqtt服務程式碼如下,需要繼承於MqttBehavior

 public class MQTTDeviceDataService : MqttBehavior, IMQTTDeviceDataService
 {
     public override async Task<bool> Authorized(string username, string password)
     {
         bool result = false;
         if (username == "admin" && password == "123456")
             result = true;
         return await Task.FromResult(result);
     }

     public async Task<bool> IsOnline(string deviceId)
     {
         return await base.GetDeviceIsOnine(deviceId);
     }

     public async Task Publish(string deviceId, WillMessage message)
     {
         var willMessage = new MqttWillMessage
         {
             WillMessage = message.Message,
             Qos = message.Qos,
             Topic = message.Topic,
             WillRetain = message.WillRetain
         };
         await Publish(deviceId, willMessage);
         await RemotePublish(deviceId, willMessage);
     }
 }

以下是測試結果:

三、總結

木舟IOT平臺會在github開源社群版本,可以自由更改程式碼,用於商業專案,但不能自營平臺,如低程式碼平臺,IOT平臺等,如有違反,後果自負,還有最好不要更改名稱空間,然後跟公司說是自己研發的,如果知道後,我在部落格全網通報此人,以前surging相關的事件就算了,就當沒發生過。,如果碰到困難,比較緊急的話,可以聯絡作者,加群:744677125

相關文章