Beispiel #1
0
        private static void printReceiveMsg(object reciveClient)
        {
            /*                   */
            /* 用来打印接收的消息*/
            /*                   */

            TcpClient client = reciveClient as TcpClient;

            if (client == null)
            {
                Console.WriteLine("client error");
                return;
            }

            try
            {
                NetworkStream stream = client.GetStream();
                while (true)
                {
                    byte[] result = new byte[1024];
                    int    num    = 0;
                    try
                    {
                        num = stream.Read(result, 0, result.Length); //将数据读到result中,并返回字符长度
                    }
                    catch (IOException ex)
                    {
                        Logger.Instance.Log(LogLevel.Warning, $"IO exception detected, client {client.Client.RemoteEndPoint.ToString()} might be disconnected");
                    }

                    if (num != 0)
                    {
                        string str = Encoding.UTF8.GetString(result, 0, num);//把字节数组中流存储的数据以字符串方式赋值给str

                        Logger.Instance.Log(LogLevel.Information, $"From: " + client.Client.RemoteEndPoint.ToString() + " : " + str);



                        try
                        {
                            var rows = str.Split(new string[] { "}{" }, StringSplitOptions.None);
                            foreach (var aRow in rows)
                            {
                                var            validatedStr = aRow.FormatValidJson();
                                HeartBeatModel heartBeat    = JsonConvert.DeserializeObject <HeartBeatModel>(validatedStr);
                                if (heartBeat.robot_id == 0)
                                {
                                    continue;
                                }

                                if (heartBeat != null)
                                {
                                    //zhu che
                                    if (heartBeat.robot_id == Const.MAIN_CAR_ID)
                                    {
                                        //update current postion
                                        RedisHelper.Instance.SetCache <HeartBeatModel>("main", heartBeat).Wait();
                                        //carInCache.CurrentPosition = new Coordinate(_heartBeat.longitude, _heartBeat.latitude);
                                        //add to the coordinate list
                                        //carInCache.CachedCoordinates.Add(new Coordinate(_heartBeat.longitude, _heartBeat.latitude));
                                        //trigger other route if possible

                                        var _cars = RedisHelper.Instance.GetCurrentCarsInCache().Result;
                                        foreach (var cachedModel in _cars)
                                        {
                                            Logger.Instance.Log(LogLevel.Information, $"checking trigger point for robot {cachedModel.CarName}");

                                            if (cachedModel.RouteStatus == 1)
                                            {
                                                Logger.Instance.Log(LogLevel.Information, $"calculating robot {cachedModel.CarName} trigger point: {cachedModel.TriggerPoint.Longitude}, {cachedModel.TriggerPoint.Latitude}. Main car long:{heartBeat.longitude}, lat: {heartBeat.latitude}");
                                                if (cachedModel.TriggerPoint.IsInRange(heartBeat.longitude,
                                                                                       heartBeat.latitude))
                                                {
                                                    //trigger the route now
                                                    //go to auto pilot mode and send the coordinates to client

                                                    Logger.Instance.Log(LogLevel.Information, $"robot {cachedModel.CarName} is getting triggered by main car");

                                                    var outbound = new OutboundModel();
                                                    outbound.CarName = cachedModel.CarName;
                                                    outbound.Data    = new List <object>();
                                                    outbound.Ip      = cachedModel.Ip;

                                                    //切换⾄数据传输模式
                                                    outbound.Data.Add(new msg_control_cmd()
                                                    {
                                                        cmd       = 1,
                                                        cmd_slave = 3,
                                                        route_id  = 0
                                                    });

                                                    //循迹驾驶
                                                    outbound.Data.Add(new msg_control_cmd()
                                                    {
                                                        cmd       = 1,
                                                        cmd_slave = 1,
                                                        route_id  = 0,
                                                        check     = 8,
                                                        speed     = cachedModel.Speed
                                                    });



                                                    RedisHelper.Instance.SetCache("command", outbound).Wait();
                                                    //update database with the

                                                    //update cache status to action
                                                    cachedModel.RouteStatus = 2;
                                                    cachedModel.IsDirty     = true;

                                                    Logger.Instance.Log(LogLevel.Information, $"dirty car found, db sync {cachedModel.CarId}");
                                                    _carDbService.SyncRoute(cachedModel).Wait();
                                                    cachedModel.IsDirty = false;
                                                }
                                            }
                                        }
                                    }
                                    //fu che
                                    else
                                    {
                                        //Check if the car is in cache
                                        //get cache car list
                                        var carInCache = RedisHelper.Instance.TryGetFromCarList($"car_{heartBeat.robot_id}").Result;

                                        var updateCache = false;

                                        if (carInCache == null)
                                        {
                                            //new robot registers

                                            carInCache = heartBeat.ToCachedRecordModel();

                                            //ADD TO DB IF NOT EXIST
                                            _carDbService.AddCarIfNotExist(carInCache);

                                            //READ FROM DB
                                            var carInDb = _carDbService.GetCarByName(heartBeat.robot_id);

                                            carInCache.CarId = carInDb.Id;
                                            carInCache.Ip    = client.Client.RemoteEndPoint.ToString();
                                            //Console.WriteLine($"attempt loading car from db: {carInDb.CarName}, {client.Client.RemoteEndPoint.ToString()}");
                                            Logger.Instance.Log(LogLevel.Information, $"attempt loading car from db: {carInCache.CarName}, {client.Client.RemoteEndPoint.ToString()}");

                                            updateCache = true;

                                            //add to the cache

                                            RedisHelper.Instance.AddCachedNameIndex(carInCache.CarName);

                                            Logger.Instance.Log(LogLevel.Information, "new robot added successfully " + client.Client.RemoteEndPoint.ToString());
                                        }
                                        else
                                        {
                                            ///Ip will change randomly upon reconnect
                                            Logger.Instance.Log(LogLevel.Information, $"loaded robot '{heartBeat.robot_id}' successfully from cache:" + client.Client.RemoteEndPoint.ToString());

                                            if (carInCache.Ip != client.Client.RemoteEndPoint.ToString())
                                            {
                                                carInCache.Ip = client.Client.RemoteEndPoint.ToString();
                                                updateCache   = true;
                                            }
                                        }

                                        if (updateCache)
                                        {
                                            var carInDb = _carDbService.GetCarByName(heartBeat.robot_id);

                                            var latestRouteIfAny = _carDbService.LatestRoute(carInDb.Id);
                                            //ready to be triggered by main car
                                            if (latestRouteIfAny != null && latestRouteIfAny.RouteStatus == 1)
                                            {
                                                carInCache.ImpotedCoordinates = latestRouteIfAny.ImportedCarTrack;
                                                carInCache.RouteId            = latestRouteIfAny.Id;
                                                carInCache.RouteStatus        = latestRouteIfAny.RouteStatus;
                                            }

                                            RedisHelper.Instance.SetCache($"car_{carInCache.CarName}", carInCache).Wait();
                                        }



                                        //fu che
                                        //verify the car status in cache consitent with client
                                        if (heartBeat.robot_status == carInCache.RobotStatus)
                                        {
                                            Console.WriteLine($"synced Robot {client.Client.RemoteEndPoint.ToString()} status {heartBeat.robot_status}");
                                            //update current position in cache
                                            carInCache.CurrentPosition = new Coordinate(heartBeat.longitude, heartBeat.latitude);
                                            carInCache.Speed           = heartBeat.speed;
                                            carInCache.Battery         = heartBeat.battery;

                                            //recording
                                            //// 1 == REMOTE CONTROL MODE
                                            if (heartBeat.robot_status == Const.ROBOT_STATUS_REMOTE)
                                            {
                                                Console.WriteLine($"remote control request: update coordinate {heartBeat.longitude}, {heartBeat.latitude}");
                                                //add the coordinate to the cache
                                                carInCache.CachedCoordinates.Add(new Coordinate(heartBeat.longitude, heartBeat.latitude));
                                            }
                                            //2 == AUTO PILOT MODE
                                            else if (heartBeat.robot_status == Const.ROBOT_STATUS_AUTO_PILOT)
                                            {
                                                //add the coordinates to the cache
                                                carInCache.CachedCoordinates.Add(new Coordinate(heartBeat.longitude, heartBeat.latitude));


                                                //is the current position within the endpoint?
                                                if (carInCache.EndPoint.IsInRange(heartBeat.longitude, heartBeat.latitude))
                                                {
                                                    //send to client to stop auto pilot mode
                                                    var outbound = new OutboundModel(carInCache.Ip, carInCache.CarName);



                                                    RedisHelper.Instance.SetCache("command", outbound).Wait();
                                                    //update database with the cached coordinates
                                                    _carDbService.UpdateRouteWithCoordinates(null, carInCache.IsReturn);
                                                    //update cache status to idle
                                                    carInCache.RouteStatus++;
                                                    //end of the process
                                                    //if (carInCache.RouteStatus == 4)
                                                    //{
                                                    //    RedisHelper.Instance.ClearKey("car_{ip}");

                                                    //}
                                                }
                                            }

                                            //update cache
                                            RedisHelper.Instance.SetCache($"car_{carInCache.CarName}", carInCache).Wait();
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Logger.Instance.Log(LogLevel.Error, e.Message);
                        }



                        //TODO REMOVE
                        //服务器收到消息后并会给客户端一个消息。
                        string msg = str;
                        result = Encoding.UTF8.GetBytes(msg);
                        //stream = client.GetStream();
                        stream.Write(result, 0, result.Length);
                        stream.Flush();
                    }
                    else
                    {   //这里需要注意 当num=0时表明客户端已经断开连接,需要结束循环,不然会死循环一直卡住
                        clients.Remove(client);

                        Console.WriteLine("client closed");

                        stream.Dispose();
                        break;
                    }
                }

                stream.Dispose();
            }
            catch (Exception e)
            {
                clients.Remove(client);
                Console.WriteLine("error:" + e.ToString());
                Logger.Instance.Log(LogLevel.Error, e.Message);
            }
        }