import 'dart:convert'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:pass_track/binding.dart'; import 'package:pass_track/pass_track.dart'; import 'dart:ffi' as ffi; import 'package:ffi/ffi.dart'; import 'package:web_socket_channel/io.dart'; import 'package:web_socket_channel/status.dart' as status; import 'package:pass_track/binding.dart' as Binding; import '../../../service/base.dart'; import '../model/coord_trans.dart'; import '../model/draw_context.dart'; import '../model/recievemodel.dart'; DrawContext drawCtx = DrawContext(); class FileHandle { int textureId = -1; int index = 0; List deviceList = []; Map deviceData = {}; String type = "cumulate"; List palette = []; //所有点的数据 List allPointData = []; //需要渲染的点的数据 List pointData = []; double L0 = 102; late CoordTrans coordTrans; /* 这个是配合原版ts更改的addpoint*/ // //过滤点 // filterPoint(var point) { // //传null,筛选所有点,并把筛选完的点全部返回,如果传入一个点,返回true或者false // if (point == null) { // //页面初始化的时候对所有的点进行筛选 // List newpointData = []; // if (pointData is List) { // for (var i = 0; i < (pointData as List).length; i++) { // if (pointData[i]['bits'] != 0) { // if (pointData[i]['count'] >= 0 && pointData[i]['count'] <= 50) { // newpointData.add(pointData[i]); // } else if (pointData[i]['type'] == 0 || pointData[i]['type'] == 2) { // newpointData.add(pointData[i]); // } // } // } // } else { // //当是个对象的时候,websocket时用 // } // pointData = newpointData; // return newpointData; // } else { // //历史的时候筛点 // if (point.runtimeType == "undefind" || // point.obj.runtimeType == "undefined") { // return false; // } // if (point["bits"] != 0) { // if (point["count"] >= 0 && point["count"] <= 50) { // return true; // } else if (point["type"] == 0 || point["type"] == 2) { // return true; // } else { // return false; // } // } else { // return false; // } // } // } //过滤点,null就是全部点,有endindex,就是回放 filterPoint(var startIndex, var endIndex) { List newpointData = []; if (endIndex == null || startIndex == null) { if (allPointData is List) { for (var i = 0; i < (allPointData as List).length; i++) { if (allPointData[i]['bits'] != 0) { if (allPointData[i]['count'] >= 0 && allPointData[i]['count'] <= 50) { newpointData.add(allPointData[i]); } else if (allPointData[i]['type'] == 0 || allPointData[i]['type'] == 2) { newpointData.add(allPointData[i]); } } } } else { //当是个对象的时候,websocket时用 } pointData = newpointData; return newpointData; } else { if (allPointData is List) { for (var i = startIndex; i < endIndex; i++) { if (allPointData[i]['bits'] != 0) { if (allPointData[i]['count'] >= 0 && allPointData[i]['count'] <= 50) { newpointData.add(allPointData[i]); } else if (allPointData[i]['type'] == 0 || allPointData[i]['type'] == 2) { newpointData.add(allPointData[i]); } } } } else { //当是个对象的时候,websocket时用 } pointData = newpointData; return newpointData; } } updateObj(pointData) { final obj = DecodeDataObj.fromBase64(pointData['data']); pointData['obj'] = obj; // var check = ffi.sizeOf() - (512 * 512 - obj.w * obj.h) * 2; var size_x = ffi.sizeOf(); // if (check < 0) { // print('check:$check'); // } ffi.Pointer pointer = calloc.allocate( ffi.sizeOf() - (512 * 512 - obj.w * obj.h) * 2 + 1000); // ffi.Pointer pointer = calloc // .allocate(size_x>>1); if (pointer == ffi.nullptr) { return; } // pointer.ref.tile.x = obj.x; // pointer.ref.tile.y = obj.y; // pointer.ref.tile.w = obj.w; // pointer.ref.tile.h = obj.h; // pointer.ref.tile.dx = obj.dx; // pointer.ref.tile.dy = obj.dy; // pointer.ref.tile.rad = obj.rad; pointer.ref.TID = pointData["TID"] as int; pointer.ref.type = pointData["type"] as int; pointer.ref.bits = pointData['bits'] == null ? 0 : pointData['bits'] as int; pointer.ref.typeBits = pointData['typeBits'] == null ? 0 : pointData['typeBits'] as int; pointer.ref.TP = (pointData["TP"]) * 1.0; pointer.ref.speed = pointData["speed"].toDouble(); pointer.ref.count = pointData["count"] as int; pointer.ref.LAT = pointData["LAT"].toDouble(); pointer.ref.LNG = pointData["LNG"].toDouble(); pointer.ref.ASL = pointData["ASL"].toDouble(); var xyh = coordTrans.d2p(CoordBLH( B: pointData["LAT"].toDouble(), L: pointData["LNG"].toDouble(), H: pointData["ASL"].toDouble())); pointer.ref.X = xyh.X * 20; pointer.ref.Y = xyh.Y * 20; pointer.ref.H = xyh.H; // print(pointer.ref.X); // print(pointer.ref.Y); // print(pointer.ref.H); pointer.ref.HDG = pointData["HDG"].toDouble(); pointer.ref.UTC = pointData["UTC"] as int; pointer.ref.layer = pointData["layer"] as int; // pointer.ref.mile = pointData["mile"] as int; pointer.ref.status = pointData["status"] as int; // for (int i = 0; i < obj.w; i++) { // //对tile处理 // for (int j = 0; j < obj.h; j++) { // if (i * obj.h + j < obj.data.length) { // pointer.ref.tile.data[i * obj.h + j] = obj.data[i * obj.h + j]; // } // } // } // passTrackPlugin.passTrack_fullMap_addPoint(pointer); //calloc.free(pointer); } Future init() async { return false; // await initDevice(); // await initPalette(); // coordTrans = CoordTrans(TransOptions(L0: L0)); // List allPointData = filterPoint(null, null); // var count = 0; // if (allPointData is List) { // for (var e in allPointData) { // count++; // updateObj(e); // // if (count > 100000) { // // break; // // // ++count // // } // } // } else { // count++; // updateObj(allPointData); // // if (count > 100000) { // // return true; // // } // } // // passTrackPlugin.passTrack_drawFullScreen(true); // ffi.Pointer pointerNull = // calloc.allocate(ffi.sizeOf()); // // passTrackPlugin.playTrack(true, true, false, 0, 115000, ffi.nullptr); // calloc.free(pointerNull); // return true; } //初始化设备,并且根据设备修改point的bits值 // initDevice() async { // //读取设备数据 // List temp = await GetServices().getDeviceBind(); // //筛出其中的roller和paver // temp.forEach((element) { // if (element["type"] == "roller" || element["type"] == "paver") { // deviceList.add(element); // } // }); // for (var i = 0; i < deviceList.length; i++) { // //对所有设备的bits进行处理 // deviceList[i]["bits"] = 1 << i; // //再将TID作为键,赋值给deviceData // deviceData[deviceList[i]["tid"]] = deviceList[i]; // } // await getFile(); // } //获取txt文件内容 // getFile() async { // var fileList = await GetServices().getHisFileList(); // for (var i = 0; i < fileList["list"].length; i++) { // // print(fileList[i]); // dynamic data = await GetServices().getHisFile(fileList["list"][i]); // allPointData.addAll(resolveJson(data, passTrackPlugin)); // } // allPointData.forEach((ele) { // updateDevices(ele); // }); // // print(pointData); // } //处理文本文件 resolveJson(var res, PassTrack passTrackPlugin) { if (res is String) { List allPointData = []; int start = 0; var allPointLen = 0; // 记录当前数组的长度 while (true) { int end = res.indexOf('\n', start); if (end < 0) { break; } String str = res.substring(start, end); try { if (str[str.length - 1] == ",") { str = str.substring(0, str.length - 1); } var item = jsonDecode(str); RecieveModel recieveModel = RecieveModel.fromJson(item); if (drawCtx.zeroDX == 0 || drawCtx.zeroDY == 0) { //dart重置中心 drawCtx.setCenter( // {"x": recieveModel.x / 20, "y": recieveModel.y / 20});//532863.8,4208668.95 {"x": 10656637 / 20, "y": 84172941 / 20});//532863.8,4208668.95 } int x = recieveModel.x; int y = recieveModel.y; int tid = recieveModel.TID; int type = recieveModel.type; var p = passTrackPlugin.wantPoint(); p.ref.X = x.toDouble(); p.ref.Y = y.toDouble(); p.ref.TID = tid; p.ref.type = type; // var data = item['data']; // if (data != null) { // item['TID'] = // item['TID'] is int ? item['TID'] : num.parse(item['TID']); // item['type'] = // item['type'] is int ? item['type'] : num.parse(item['type']); // item['obj'] = DecodeDataObj.fromBase64(item['data']); // // this.updateDevice(item); // // this.sportsData.push(item); allPointData.add(recieveModel); // } } catch (e) { print("----$e\r\n$str"); } allPointLen++; start = end + 1; } return allPointLen; } else { //只有一条数据的时候 var item = res; var data = item['data']; if (data != null) { item['obj'] = DecodeDataObj.fromBase64(item['data']); item['type'] = num.parse(item['type']); item['TID'] = num.parse(item['TID']); // this.updateDevice(item); // this.sportsData.push(item); } return 1; } } //修改点的bits和typeBits updateDevices(var point) { var TID = point["TID"]; if (deviceData.containsKey(TID)) { var device = deviceData[TID]; device["show"] = true; point["bits"] = device["bits"]; point["typeBits"] = (device["type"] == "paver" ? 2 : 1) < 2 ? 1 : device["bits"] | (1 << ((device["type"] == "paver" ? 2 : 1) - 2)); device["point"] = point; } //bug //websocket // if(isLive ==true&&devicState.timer==null){ // //设置了一个定时器 // } } //读取颜色 // initPalette() async { // var data = await GetServices().getLayeConfig(); // for (var i = 0; i < data.length; i++) { // if (data[i]['name'] == "times_draw") { // data[i] = filterAndResolveModel(data[i]); // } // data[i] = FormatColor(data[i]); // if (data[i]['type'] == 'layer' && data[i]["standard"] != null) { // data[i] = BubbleSort(data[i]); // } // } // palette = data[0]["color"]; // //给调色板赋值 // for (int i = 0; i < palette.length; i++) { // passTrackPlugin.setPalette(i, changeARGBInt8toInt32(palette[i])); // } // // print(palette); // // print(palette.length); // //如果是cumulate类型还要对颜色进行扩充 // } List liveData = []; bool isLive = false; var devicState; num centerTid = 0; // 是否结束播放 bool end = true; var sportsData; num angle = 0; // 中心设备的编号 var centerDevice = null; bool isCenter = false; //是否平移 bool isTranslate = false; // 正北模式 bool isView = false; int? startIndex; int? endIndex; //websocket liveView(bool isLive, String wsHost, String proj_code) { String token = ""; String ws_url = wsHost + "?token=" + token; final _channel = IOWebSocketChannel.connect(ws_url); String? message; //发送消息 _channel.sink.add(jsonEncode(["ProjSubscribe", "cp_road", proj_code])); _channel.stream.listen((message) { //检查收到数据 List data = json.decode(message); if (data[0] == "ProjSubAck") { //如果响应的数据不正确,重新发送信息 if (proj_code != data[2]) { _channel.sink .add(jsonEncode(["ProjSubscribe", "cp_road", proj_code])); } //bug,这里应该还有些操作 //绘制设备,绘制数据, } else if (data[0] == "cp_roadPublish") { if (proj_code != data[2]) {} var row = data[3]; row.obj = DecodeDataObj.fromBase64(row.data); row.TID = num.parse(row.TID); liveData.add(row); recivePoint(row); updateDevices(row); //有tid,以当前设备为中心 if (centerTid != 0 && row.TID == centerTid) { //bug //这里申请地址,创建一个point传给c++ // passTrackPlugin.passTrack_fullMap_updateCenter(point); drawCtx.setCenter(row.obj); } //如果该点不符合要求直接return if (!filterPoint(null, null).isNotEmpty) { return; } if (end && isLive) { var socketInfo; sportsData.addAll(liveData); liveData.clear(); if (angle == 0) { angle = pi / 2 - row.obj.rad; socketInfo.rotate = (180 / pi) * angle; socketInfo.TP = row.TP; socketInfo.speed = row.speed; socketInfo.LAT = row.LAT; socketInfo.LNG = row.LNG; } else if (row.bits == centerDevice) { angle = pi / 2 - row.obj.rad; socketInfo.rotate = (180 / pi) * angle; socketInfo.TP = row.TP; socketInfo.speed = row.speed; socketInfo.LAT = row.LAT; socketInfo.LNG = row.LNG; if (isCenter) { backCenter(); } } socketInfo.count = row.count; // this.eventObject['socketing']?.call(this, socketInfo); } if (!this.isTranslate) { //bug 局部重绘 // this.fillAndDrawImageData(false, row); if (isView || !centerDevice) { //bug // centerDevice= } } } }); } recivePoint(var point) { if (drawCtx.zeroDX == 0 || drawCtx.zeroDY == 0) { //dart重置中心 drawCtx.setCenter(point); //bug //c++重置中心 ffi.Pointer pointer = calloc.allocate(ffi.sizeOf()); // pointer.ref.x // passTrackPlugin.playTrack( // true, false, false, 0, -1, pointer); calloc.free(pointer); } //bug //这里要申请地址,然后把point传给c++ // passTrackPlugin.passTrack_fullMap_addPoint(point); // passTrackPlugin.passTrack_drawFullScreen(true); //这是c++addpoint后的返回值 bool isSucceed = true; if (isSucceed) { isCenter = true; } else { isCenter = false; } } //返回中心坐标 backCenter() { //bug //应该可以和刷新一样 } drawSection(int startIndex, int endIndex, bool isCenter) { if (endIndex > allPointData.length) { return; } if (isCenter) { filterPoint(startIndex, endIndex); } else {} } // drawSection(int startIndex, int endIndex, bool isCenter) { // if (startIndex < 0 && endIndex < 0) { // return; // } // //清空屏幕 // //bug // // this.ctx.clearRect(0, 0, this.width, this.height); // // this.global.data.fill(0); // updateDeviceVisible(); // if (isCenter || drawCtx.zeroDX == 0 || drawCtx.zeroDY == 0) { // if (sportsData[endIndex]["obj"] != null) { // double ox = sportsData[endIndex]["obj"]["x"]; // double oy = sportsData[endIndex]["obj"]["y"]; // num x = ((ox / drawCtx.scale - drawCtx.screenSize.width / 2) - // drawCtx.zeroDX) // .floor() // .abs(); // num y = ((oy / drawCtx.scale - drawCtx.screenSize.height / 2) - // drawCtx.zeroDY) // .floor() // .abs(); // if (x >= drawCtx.screenSize.width / 2 || // y >= drawCtx.screenSize.height / 2) { // drawCtx.zeroX = ox; // drawCtx.zeroY = oy; // drawCtx.setCenter(null); // } // } // } // reciveAndFilterPoint(startIndex, endIndex); // //绘制全屏 // // this.fillAndDrawImageData(true); // //绘制网格 // // this.drawGrid(); // //绘制道路边线 // // this.drawSideLine(this.roadData); // //获取设备 // // let arr = this.getDeviceData(); // //绘制设备 // // this.drawDevice(arr); // endIndex = endIndex; // startIndex = startIndex; // //监听当前视图状态 播放进度 // // this.viewStatus(false); // // this.isPlay = false; // } // //筛选出需要绘制的设备 // updateDeviceVisible() { // for (int i = 0; i < deviceList.length; i++) { // if (deviceList[i] != null) { // deviceList[i]["show"] = true; // } else { // deviceList[i]["show"] = false; // } // } // } // reciveAndFilterPoint(int startIndex, int endIndex) { // if (endIndex == -1) { // endIndex = sportsData.length - 1; // } // for (int i = startIndex; i <= endIndex; i++) { // var isDraw = filterPoint(sportsData[i]); // if (isDraw) { // recivePoint(sportsData[i]); // updateDevices(sportsData[i]); // // this.allowDLPI = index; // } // } // } } //将后端的rgba转换成abgr,因为c++那边渲染需要abgr int changeARGBInt8toInt32(List row) { int result; result = (row[3] << 24) | (row[2] << 16) | (row[1] << 8) | row[0]; return result; } //根据standard处理color的值 Map filterAndResolveModel(Map item) { item["standard"] = tranToArray(item["standard"]); item["color"] = tranToArray(item["color"]); var standard = item["standard"]; var color = item["color"]; for (var i = 0; i < standard.length; i++) { var inter = standard[i]; var actColor = color[i]; var interDiff = inter[1] - inter[0]; var colorDiff1 = ((actColor[0][0] - actColor[1][0]) / interDiff).round().abs(); var colorDiff2 = ((actColor[0][1] - actColor[1][1]) / interDiff).round().abs(); var colorDiff3 = ((actColor[0][2] - actColor[1][2]) / interDiff).round().abs(); var arr = []; for (var j = 1; j < interDiff; j++) { arr.add([ actColor[0][0] - colorDiff1 * j, actColor[0][1] - colorDiff2 * j, actColor[0][2] - colorDiff3 * j, 255 ]); } actColor.insert(1, arr); } var newStandard = []; for (var i = 0; i < standard.length; i++) { for (var j = 0; j < standard[i].length; j++) { newStandard.add(standard[i][j]); } } item["standard"] = newStandard; var newColor = []; for (var i = 0; i < color.length; i++) { for (var j = 0; j < color[i].length; j++) { for (var k = 0; k < color[i][j].length; k++) { if (color[i][j][k] is int) { newColor.add(color[i][j]); break; } else { newColor.add(color[i][j][k]); } } } } item["color"] = newColor; return item; } List tranToArray(List arr) { var newArr = []; for (var i = 0; i < arr.length; i += 2) { newArr.add([arr[i], arr[i + 1]]); } return newArr; } //对于类型是cumulate的颜色扩充到256,对于非cumulate的颜色添加一个白色的初始色 Map FormatColor(Map item) { if (item["type"] == "cumulate") { List newColor = []; for (int i = 1; i < item["color"].length; i++) { newColor.addAll([ item["color"][i], item["color"][i], item["color"][i], item["color"][i] ]); } item["color"] = newColor; var maxColor = item["color"][item["color"].length - 1]; for (var i = item["color"].length; i < 254; i++) { item["color"].add(maxColor); } item["color"].insert(0, [0, 0, 0, 0]); item["color"].insert(0, [0, 0, 0, 0]); } else { item["color"].insert(0, [0, 0, 0, 0]); } if (item["sideColor"] != null && item["sideColor"] != 0) { item["color"][1] = item["sideColor"]; } return item; } //如果类型是layer,重新对standard和color排序 Map BubbleSort(Map item) { for (var i = 0; i < item["standard"].length; i++) { for (var j = 1; j < item["standard"].length; j++) { if (item["standard"][i] > item["standard"][j]) { var num = item["standard"][i]; item["standard"][i] = item["standard"][j]; item["standard"][j] = num; var color = item["color"][i]; item["color"][i] = item["color"][j]; item["color"][j] = color; } } } return item; }