『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
楼主: ryanh7

[技术探讨] 新坑:air780eg定位器diy

  [复制链接]

77

主题

1413

帖子

2万

积分

元老级技术达人

积分
27147
金钱
25694
HASS币
290
发表于 2025-2-20 09:52:06 | 显示全部楼层
本帖最后由 dscao 于 2025-2-20 10:12 编辑

参数中的定位: 全部启用但不上报

参数配置中的任务(目前最后的代码,应该还有很多可以优化的):

function 
    sys.wait(15000) 
    local taskname="userTask" 
    log.info(taskname,"start")
    local nid=1
    local uid=1
    local netsta =0
    local needup =1
    local needupall =1
    local count =0
    local count2 =0
    local count3 =0
    local shake=0
    local thisshake=0
    local lastshake=0
    local acc=1
    local run=0
    local adc =0
    local e ={}
    local lbslng =0
    local lbslat =0
    local gpslng =0
    local gpslat =0
    local gpsisfix =0
    GpsInit()
    GpsExecAgnss()
    e.adc=0
    PronetStopProRecCh(1)
UartStopProRecCh(1) --如果串口数据还需要透传,需要删除
    local EARTH_RADIUS = 6378.137
    local function getDistance(lat1,lng1,lat2,lng2)
            local radLat1 = lat1 * math.pi / 180.0
            local radLat2 = lat2 * math.pi / 180.0
            local a = radLat1 - radLat2
            local b = lng1 * math.pi / 180.0 - lng2  * math.pi / 180.0
            local s = 2 * math.asin(math.sqrt(math.pow(math.sin(a/2),2) + math.cos(radLat1)*math.cos(radLat2)*math.pow(math.sin(b/2),2)))
            s = s * EARTH_RADIUS
            return s*1000
    end
    local function calculateBearing(lat1, lng1, lat2, lng2)
            local deltaLng = math.rad(lng2 - lng1)
            lat1 = math.rad(lat1)
            lat2 = math.rad(lat2)
            local y = math.sin(deltaLng) * math.cos(lat2)
            local x = math.cos(lat1) * math.sin(lat2) - math.sin(lat1) * math.cos(lat2) * math.cos(deltaLng)
            local bearing = math.deg(math.atan2(y, x))
            return (bearing + 360) % 360
    end
    while true do
             --解析网络数据
    netr = PronetGetRecChAndDel(nid)
    if netr then 
        log.info(taskname,"netr data",netr)
        local j =json.decode(netr)
        if j and type(j)=="table" and j.cmd then 
            if j.cmd =="on1" then 
                PerSetDo(1,1)
            elseif j.cmd =="off1" then 
                PerSetDo(1,0)
            elseif j.cmd =="on2" then 
                PerSetDo(2,1)
            elseif j.cmd =="off2" then 
                PerSetDo(2,0)
            elseif j.cmd =="onoff2" then 
                PerSetDo(2,1)
                sys.wait(1000)
                PerSetDo(2,0)
            elseif j.cmd =="dw" then  --立即定位
                needupall =1
            end 
            local jb={}
            jb.cmd =j.cmd
            jb.res =1
            jb.In1=PerGetDoSta(1)
            jb.In2=PerGetDoSta(2)
            jb.csq=mobile.csq()
            local bck = json.encode(jb)
            if j.cmd ~="dw" and bck and 1==PronetGetNetSta(nid) then 
                PronetSetSendCh(nid,bck)
            end 
            local jb={}
        end 
    end        

            local d ={}
            if needupall ==1 then
                    d.t=os.date("%Y-%m-%d %H:%M:%S")
                    d.csq=mobile.csq()
                    d.In1=PerGetDoSta(1)
                    d.In2=PerGetDoSta(2)
            end
            adc =tonumber(PerGetAdcGatherValByAdcId(1)) 
            if math.abs(e.adc-adc) >1000 or needupall ==1 then
                    d.adc = adc
                    e.adc = d.adc
                    needup =1
            end
            acc=PerGetDiById(1)
            if needupall ==1 or e.acc~=acc then
                    d.acc=acc
                    e.acc=acc
                    needup =1
            end
            thisshake = PerGetGpsZdSta()
            if thisshake == lastshake then
                    count3 = count3+1
            else
                    count3 = 0
            end
            lastshake = thisshake
            if thisshake == 1  and count3>2  then
                    shake = 1
            end
            if thisshake == 0 and count3>30 then
                    shake = 0
            end
            if  needupall ==1 or e.s ~= shake then
                    d.s = shake
                    e.s = shake
                    needup =1
            end
            if libgnss.isFix() then
                    gpsisfix = 1
            else
                    gpsisfix = 0
            end
            if  needupall ==1 or e.f~=gpsisfix then
                    d.f=gpsisfix
                    e.f=d.f
                    needup =1
            end
            if libgnss.isFix() then 
                    local tg =libgnss.getRmc(2)
                    local m = getDistance(tg.lat,tg.lng,gpslat,gpslng)
                    d.m = m
                    d.gps={}
                    d.gps.lat,d.gps.lng=tg.lat,tg.lng
                    d.gps.speed=tg.speed * 1.85
                    d.gps.course = calculateBearing(tg.lat,tg.lng,gpslat,gpslng)
                    if needup ==1 then
                            gpslat,gpslng = d.gps.lat,d.gps.lng
                    end
            end
            lbslng,lbslat = GetLbs()
            if  needupall ==1 or e.lbslng ~= lbslng then
                    d.lbs={}
                    d.lbs.lng,d.lbs.lat=lbslng,lbslat
                    e.lbslng,e.lbslat=lbslng,lbslat
            end
            local updata = json.encode(d)
            local netsta = PronetGetNetSta(nid)
            log.info(taskname,"updata",updata,"netsta",netsta)
            if needup ==1 and updata and next(d)~=nil and netsta ==1 then 
                    needup =0
                    needupall =0
                    count =0
                    PronetSetSendCh(nid,updata)
            end
            count = count+1
            count2 = count2+1
            if (acc ==0 or e.s ==1) and count > 15 then
                    needup =1
            end
            if e.s ==1 and libgnss.isFix() == false  and count2 > 300 then
                    GpsSetPower(0)
                    sys.wait(1000)
                    GpsSetPower(1)
                    sys.wait(1000)
                    GpsExecAgnss()
                    count2 =0
            end
            if count > 600 then 
                    needup =1
                    needupall =1
            end 
            sys.wait(1000)
    end 
end


Nodered端需要做缓存及转化,上报时没有的数据使用缓存,有新的数据更新缓存对应值,最后输出实体。最好再做一下空值过滤,避免特殊情况下实体状态间接性出现短暂unknown导致墨澜地图无法显示轨迹。

20250220094954.jpg

之前想用计算运动状态或移动距离来控制上报频率,实际体验非常不好,最后还是改为震动状态或ACC状态控制,ACC接线不太方便,实际使用中还是以震动来判断的,这里震动传感器持续震动2秒后将shake=1,持续静止30秒后shake=0 ,因为实测中发现行驶过程中震动传感器也会偶偶触发静止,所以加入了ha中自动化中状态持续时间的思路。

我也在关注楼主的固件和集成的进展情况,暂时mqtt方式先用着。

评分

参与人数 1金钱 +2 收起 理由
ahu + 2 GPS 定位一直不行,只到我用了这段代码!.

查看全部评分

回复

使用道具 举报

59

主题

333

帖子

5621

积分

元老级技术达人

积分
5621
金钱
5273
HASS币
100
 楼主| 发表于 2025-2-20 14:26:22 | 显示全部楼层
dscao 发表于 2025-2-20 09:52
参数中的定位: 全部启用但不上报

参数配置中的任务(目前最后的代码,应该还有很多可以优化的):

震动电阻确实不太靠谱,容易在行驶过程中识别为静止(影响严重),或者在静止时识别为运动(影响较小)。有ACC的情况下还是使用ACC判断比较靠谱。没有ACC的情况下才用震动判断(主要用于判断长时间没有震动后休眠,可能会延长定位器开机)。其余逻辑还是放到服务端处理比较好。现在主要问题还是定位漂移
回复

使用道具 举报

0

主题

145

帖子

1208

积分

金牌会员

Rank: 6Rank: 6

积分
1208
金钱
1063
HASS币
0
发表于 7 天前 | 显示全部楼层
666大佬们牛逼,期待固件和集成
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2025-3-4 20:05 , Processed in 0.106403 second(s), 27 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表