Newer
Older
SensorHub-NoiseCorr / SensorHub.Servers / CasicServer433.cs
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol;
using System.Collections.Generic;
using System;
using Quartz;
using Quartz.Impl;
using SensorHub.Utility;
using System.Timers;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using SensorHub.Servers.JsonFormat;
using SensorHub.Servers.Commands.CASICCommands;
using StackExchange.Redis;
using System.Threading;
using System.Diagnostics;
using SensorHub.Config;

namespace SensorHub.Servers
{
    public class CasicServer433 : AppServer<CasicSession>, IDespatchServer
    {
        RedisHelper redis = new RedisHelper(0);//依赖Redis的可靠性,如果Redis服务停止,需要重启本程序,希望以后可以改善
        private List<String> concentratorThreadList = new List<String>();

        //public static Dictionary<String, String> concentratorWithSessionIdMap = new Dictionary<String, String>();

        public CasicServer433()
            : base(new DefaultReceiveFilterFactory<CasicReceiveFilter433, StringRequestInfo>())
        {

        }

        protected override void OnStarted()
        {
            redis.Subscribe("Config", (channel, message) =>
            {
                //输出收到的订阅消息  
                Logger.Info("收到订阅的Config消息:" + message);

                String[] concentratorCodes = message.ToString().Split(',');
                
                foreach (var concentratorCode in concentratorCodes)
                {
                    if (!Common.concentratorWithSessionIdMap.ContainsKey(concentratorCode))
                    {
                        return;
                    }

                    if (!concentratorThreadList.Contains(concentratorCode))
                    {
                        Thread t = new Thread(doSendConfig);
                        t.Start(concentratorCode);

                        concentratorThreadList.Add(concentratorCode);
                    }
                }
            });
        }

        private void doSendConfig(object msg) //下发配置线程
        {
            String code = msg as String;
            Dictionary<String, int> devWithMaxSendNumbers = new Dictionary<String, int>();

            try
            {
                while (true)
                {
                    String devcodes = redis.ListRightPop<String>(code);
                    if (string.IsNullOrEmpty(devcodes))
                    {
                        break;
                    }

                    if (!devcodes.Contains(":"))
                    {
                        devcodes += ":1";
                    }

                    String[] devcode = devcodes.Split(':');//设备编号:尝试次数

                    Logger.Info("设备[" + devcode[0] + "]剩余主动下发配置尝试次数:" + devcode[1]);

                    String devCode = devcode[0].Replace("$", "").Substring(0,12);
                    String devType = devCode.Substring(0, 2);
                    int interval = 0;//下发时间间隔
                    byte routeflag = 0x01;//通信方式,路灯为05
                    if (devType == "72" || devType == "73" || devType == "74")//路灯时间长
                    {
                        interval = int.Parse(System.Configuration.ConfigurationManager.AppSettings["Lamp_Interval"]);
                        routeflag = 0x05;
                    }
                    else
                    {
                        interval = int.Parse(System.Configuration.ConfigurationManager.AppSettings["Concentrator_Interval"]);
                        //interval = 10000;
                    }

                    String configItem = redis.StringGet(devcode[0]);
                    if (string.IsNullOrEmpty(configItem))
                    {
                        redis.ListRemove<String>(code, devcode[0]);
                        Logger.Info("设备[" + devcode[0] + "]已下发成功,下发配置项为空");
                        continue;
                    }

                    byte[] config = null;

                    if (configItem.Contains("collect"))
                    {
                        config = ConfigBuild.buildQueryFrame(devCode);
                    }
                    else
                    {
                        config = ConfigBuild.build433ConfigFrame(devCode, configItem);
                    }
                    config[10] = routeflag;//通信方式

                    DispatchMessage(code, config);

                    int num = int.Parse(devcode[1]);
                    if (--num > 0)
                    {
                        if (devcode[0].Contains("$"))
                        {
                            redis.ListRightPush<String>(code, devcode[0] + ":" + num.ToString());
                        }
                        else
                        {
                            redis.ListLeftPush<String>(code, devcode[0] + ":" + num.ToString());
                        }

                    }
                    Thread.Sleep(interval);

                }

            }
            catch (Exception ex)
            {
                Logger.Error("下发配置错误:" + ex.ToString());
            }
            finally
            {
                if (concentratorThreadList.Contains(code))
                {
                    concentratorThreadList.Remove(code);
                }
            }
        }


        protected override void OnSessionClosed(CasicSession session, CloseReason reason)
        {
            if (session.HubAddr != null)
            {
                //集中器离线,给第三方发信息
                if (Common.concentratorWithSessionIdMap.ContainsKey(session.HubAddr))
                {
                    Logger.Info("集中器离线,移除连接:" + session.HubAddr + "," + session.SessionID);
                    Common.concentratorWithSessionIdMap.Remove(session.HubAddr);
                }

                DateTime now = DateTime.Now;
                DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); //当地时区
                long timeStamp = (long)(now - startTime).TotalMilliseconds; //相差毫秒数
                String logtime = now.ToString("yyyy") + now.ToString("MM") + now.ToString("dd")
                    + now.ToString("HH") + now.ToString("mm") + now.ToString("ss");

                String message = JsonConvert.SerializeObject(new Json("Event", "Concentrator", session.HubAddr,
                       new DataJson("ConcentratorOffline", -1, null, logtime), timeStamp));

                if (Common.SendMessage(message))
                {
                    session.Logger.Info("往第三方发送数据:" + message);
                }
                else
                {
                    session.Logger.Info("未连接上第三方服务器");
                }
            }
            base.OnSessionClosed(session, reason);
        }


        public void DispatchMessage(string devCode, byte[] config)
        {
            if (Common.concentratorWithSessionIdMap.ContainsKey(devCode))
            {
                String sessionID = Common.concentratorWithSessionIdMap[devCode];
                Logger.Info("集中器设备编号:" + devCode + "," + sessionID);
                CasicSession s = this.GetSessionByID(sessionID);

                if (s != null && s.Connected)
                {
                    //增加CRC校验
                    String strCrc = StringUtil.To16HexString(String.Format("{0:X}", (int)CodeUtils.CRC16_AD(config)));
                    byte[] btcrc = { CodeUtils.String2Byte(strCrc.Substring(0, 2)), CodeUtils.String2Byte(strCrc.Substring(2, 2)) };
                    byte[] afcrc = new byte[config.Length + 2];
                    config.CopyTo(afcrc, 0);
                    btcrc.CopyTo(afcrc, config.Length);

                    Logger.Info("主动下发配置信息:" + BitConverter.ToString(afcrc).Replace("-", ""));
                    s.Send(afcrc, 0, afcrc.Length);
                }
                else
                {
                    Logger.Info("主动下发配置失败,连接不存在或已断开");
                }
            }


            //foreach (CasicSession session in this.GetAllSessions())
            //{
            //    //可以改进
            //    session.Logger.Info("集中器设备编号:" + session.HubAddr + "," + session.SessionID);

            //    if (session.HubAddr == devCode && devCode != null)
            //    {
            //        //增加CRC校验
            //        String strCrc = StringUtil.To16HexString(String.Format("{0:X}", (int)CodeUtils.CRC16_AD(config)));
            //        byte[] btcrc = { CodeUtils.String2Byte(strCrc.Substring(0, 2)), CodeUtils.String2Byte(strCrc.Substring(2, 2)) };
            //        byte[] afcrc = new byte[config.Length + 2];
            //        config.CopyTo(afcrc, 0);
            //        btcrc.CopyTo(afcrc, config.Length);

            //        session.Logger.Info("主动下发配置信息:" + BitConverter.ToString(afcrc).Replace("-", ""));
            //        session.Send(afcrc, 0, afcrc.Length);
            //    }
            //}
        }
    }
}