首页
导航
统计
留言
更多
壁纸
直播
关于
推荐
星的魔法
星的导航页
谷歌一下
镜像国内下载站
大模型国内下载站
docker镜像国内下载站
腾讯视频
Search
1
Ubuntu安装 kubeadm 部署k8s 1.30
356 阅读
2
kubeadm 部署k8s 1.30
239 阅读
3
rockylinux 9.3详细安装drbd
216 阅读
4
k8s 高可用部署+升级
172 阅读
5
rockylinux 9.3详细安装drbd+keepalived
165 阅读
默认分类
日记
linux
docker
k8s
ELK
Jenkins
Grafana
Harbor
Prometheus
Cepf
k8s安装
Gitlab
traefik
sonarqube
OpenTelemetry
MinIOn
Containerd进阶使用
ArgoCD
nexus
test
›
test2
test3
istio
golang
Git
Python
Web开发
HTML和CSS
JavaScript
对象模型
公司
zabbix
zookeeper
hadoop
登录
/
注册
Search
标签搜索
k8s
linux
docker
drbd+keepalivde
ansible
dcoker
webhook
星
累计撰写
156
篇文章
累计收到
1,007
条评论
首页
栏目
默认分类
日记
linux
docker
k8s
ELK
Jenkins
Grafana
Harbor
Prometheus
Cepf
k8s安装
Gitlab
traefik
sonarqube
OpenTelemetry
MinIOn
Containerd进阶使用
ArgoCD
nexus
test
test2
test3
istio
golang
Git
Python
Web开发
HTML和CSS
JavaScript
对象模型
公司
zabbix
zookeeper
hadoop
页面
导航
统计
留言
壁纸
直播
关于
推荐
星的魔法
星的导航页
谷歌一下
镜像国内下载站
大模型国内下载站
docker镜像国内下载站
腾讯视频
搜索到
154
篇与
的结果
2026-02-05
飞书通知开发
一、代码#初始化目录 cd ~ mkdir feishu-forwarder cd feishu-forwarder go mod init feishu-forwarder #Dockerfile FROM golang:1.24.2-alpine AS build WORKDIR /src COPY go.mod ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o /out/feishu-forwarder . FROM gcr.io/distroless/static:nonroot COPY --from=build /out/feishu-forwarder /feishu-forwarder EXPOSE 8080 USER nonroot:nonroot ENTRYPOINT ["/feishu-forwarder"] #main.go package main import ( "bytes" "context" "crypto/hmac" "crypto/sha256" "encoding/base64" "encoding/hex" "encoding/json" "io" "log" "math/rand" "net/http" "os" "sort" "strings" "sync" "time" ) type Alert struct { Status string `json:"status"` Labels map[string]string `json:"labels"` Annotations map[string]string `json:"annotations"` StartsAt string `json:"startsAt"` EndsAt string `json:"endsAt"` GeneratorURL string `json:"generatorURL"` Fingerprint string `json:"fingerprint"` // Alertmanager webhook 通常会带;没有也没关系 } type AMPayload struct { Status string `json:"status"` Receiver string `json:"receiver"` ExternalURL string `json:"externalURL"` GroupKey string `json:"groupKey"` CommonLabels map[string]string `json:"commonLabels"` Alerts []Alert `json:"alerts"` } // webhook body:text 用 content;card 用 card type FeishuBody struct { Timestamp string `json:"timestamp,omitempty"` Sign string `json:"sign,omitempty"` MsgType string `json:"msg_type"` Content map[string]interface{} `json:"content,omitempty"` Card map[string]interface{} `json:"card,omitempty"` } type Target struct { Webhook string Secret string Name string // 用于日志 } type Config struct { // 路由:按 severity 选择目标群 WebhooksCritical string WebhooksWarning string WebhooksDefault string SecretCritical string SecretWarning string SecretDefault string // 消息类型:card / text MsgType string // 去重窗口 DedupTTL time.Duration // 重试 RetryMax int RetryBase time.Duration // 限流(全局) RateQPS float64 RateBurst int // HTTP SendTimeout time.Duration } func loadConfig() Config { cfg := Config{ WebhooksCritical: strings.TrimSpace(os.Getenv("FEISHU_WEBHOOKS_CRITICAL")), WebhooksWarning: strings.TrimSpace(os.Getenv("FEISHU_WEBHOOKS_WARNING")), WebhooksDefault: strings.TrimSpace(os.Getenv("FEISHU_WEBHOOKS_DEFAULT")), SecretCritical: strings.TrimSpace(os.Getenv("FEISHU_SECRET_CRITICAL")), SecretWarning: strings.TrimSpace(os.Getenv("FEISHU_SECRET_WARNING")), SecretDefault: strings.TrimSpace(os.Getenv("FEISHU_SECRET_DEFAULT")), MsgType: strings.ToLower(strings.TrimSpace(os.Getenv("FEISHU_MSG_TYPE"))), DedupTTL: mustParseDuration(getEnvDefault("DEDUP_TTL", "10m")), RetryMax: mustParseInt(getEnvDefault("RETRY_MAX", "3")), RetryBase: mustParseDuration(getEnvDefault("RETRY_BASE", "300ms")), RateQPS: mustParseFloat(getEnvDefault("RATE_QPS", "2")), // 每秒2条 RateBurst: mustParseInt(getEnvDefault("RATE_BURST", "5")), // 突发5条 SendTimeout: mustParseDuration(getEnvDefault("SEND_TIMEOUT", "6s")), } if cfg.MsgType != "text" && cfg.MsgType != "card" { cfg.MsgType = "card" } // 兼容:如果你只设置了旧的 FEISHU_WEBHOOKS/FEISHU_SECRET if cfg.WebhooksDefault == "" { cfg.WebhooksDefault = strings.TrimSpace(os.Getenv("FEISHU_WEBHOOKS")) } if cfg.SecretDefault == "" { cfg.SecretDefault = strings.TrimSpace(os.Getenv("FEISHU_SECRET")) } return cfg } /* ============ 去重(内存 TTL) ============ */ type Deduper struct { mu sync.Mutex ttl time.Duration data map[string]time.Time } func NewDeduper(ttl time.Duration) *Deduper { d := &Deduper{ ttl: ttl, data: make(map[string]time.Time), } go d.gcLoop() return d } func (d *Deduper) Allow(key string) bool { if d.ttl <= 0 { return true } now := time.Now() d.mu.Lock() defer d.mu.Unlock() if t, ok := d.data[key]; ok { if now.Sub(t) < d.ttl { return false } } d.data[key] = now return true } func (d *Deduper) gcLoop() { t := time.NewTicker(1 * time.Minute) defer t.Stop() for range t.C { now := time.Now() d.mu.Lock() for k, v := range d.data { if now.Sub(v) > d.ttl*2 { delete(d.data, k) } } d.mu.Unlock() } } /* ============ 简单全局限流(token bucket) ============ */ type RateLimiter struct { ch chan struct{} stop chan struct{} } func NewRateLimiter(qps float64, burst int) *RateLimiter { if qps <= 0 { return nil } if burst < 1 { burst = 1 } rl := &RateLimiter{ ch: make(chan struct{}, burst), stop: make(chan struct{}), } // 初始塞满 burst for i := 0; i < burst; i++ { rl.ch <- struct{}{} } interval := time.Duration(float64(time.Second) / qps) if interval < 10*time.Millisecond { interval = 10 * time.Millisecond } go func() { t := time.NewTicker(interval) defer t.Stop() for { select { case <-t.C: select { case rl.ch <- struct{}{}: default: } case <-rl.stop: return } } }() return rl } func (rl *RateLimiter) Acquire(ctx context.Context) error { if rl == nil { return nil } select { case <-ctx.Done(): return ctx.Err() case <-rl.ch: return nil } } /* ============ 飞书签名 ============ */ func genFeishuSign(secret, timestamp string) string { stringToSign := timestamp + "\n" + secret mac := hmac.New(sha256.New, []byte(stringToSign)) sum := mac.Sum(nil) return base64.StdEncoding.EncodeToString(sum) } /* ============ severity 路由 ============ */ func getSeverity(p AMPayload) string { s := strings.ToLower(strings.TrimSpace(p.CommonLabels["severity"])) if s == "" && len(p.Alerts) > 0 { s = strings.ToLower(strings.TrimSpace(p.Alerts[0].Labels["severity"])) } switch s { case "critical", "fatal", "sev0", "sev1": return "critical" case "warning", "warn", "sev2": return "warning" default: return "default" } } func splitWebhooks(s string) []string { s = strings.TrimSpace(s) if s == "" { return nil } parts := strings.Split(s, ",") var out []string for _, x := range parts { x = strings.TrimSpace(x) if x != "" { out = append(out, x) } } return out } func selectTargets(cfg Config, sev string) []Target { var whs []string var secret string var name string switch sev { case "critical": whs = splitWebhooks(cfg.WebhooksCritical) secret = cfg.SecretCritical name = "critical" case "warning": whs = splitWebhooks(cfg.WebhooksWarning) secret = cfg.SecretWarning name = "warning" default: whs = splitWebhooks(cfg.WebhooksDefault) secret = cfg.SecretDefault name = "default" } // fallback:如果 critical/warning 没配,则退回 default if len(whs) == 0 { whs = splitWebhooks(cfg.WebhooksDefault) secret = cfg.SecretDefault name = "default(fallback)" } var out []Target for _, w := range whs { out = append(out, Target{Webhook: w, Secret: secret, Name: name}) } return out } /* ============ 去重 key ============ */ func alertKey(a Alert) string { if a.Fingerprint != "" { return a.Fingerprint } // 没 fingerprint 就用 labels 自己算一个稳定 hash keys := make([]string, 0, len(a.Labels)) for k := range a.Labels { keys = append(keys, k) } sort.Strings(keys) var b strings.Builder for _, k := range keys { b.WriteString(k) b.WriteString("=") b.WriteString(a.Labels[k]) b.WriteString(";") } sum := sha256.Sum256([]byte(b.String())) return hex.EncodeToString(sum[:]) } /* ============ 消息构建 ============ */ func formatText(p AMPayload, alerts []Alert) string { var b strings.Builder b.WriteString("【Alertmanager】" + strings.ToUpper(p.Status) + "\n") if v := p.CommonLabels["alertname"]; v != "" { b.WriteString("alertname: " + v + "\n") } if v := p.CommonLabels["severity"]; v != "" { b.WriteString("severity: " + v + "\n") } b.WriteString("alerts: ") b.WriteString(intToString(len(alerts))) b.WriteString("\n\n") for i, a := range alerts { b.WriteString("#") b.WriteString(intToString(i + 1)) b.WriteString(" ") if an := a.Labels["alertname"]; an != "" { b.WriteString(an) } if inst := a.Labels["instance"]; inst != "" { b.WriteString(" @ " + inst) } b.WriteString("\n") if s := a.Annotations["summary"]; s != "" { b.WriteString("summary: " + s + "\n") } if d := a.Annotations["description"]; d != "" { b.WriteString("desc: " + d + "\n") } if a.GeneratorURL != "" { b.WriteString("url: " + a.GeneratorURL + "\n") } b.WriteString("\n") } return b.String() } func buildCard(p AMPayload, sev string, alerts []Alert) map[string]interface{} { alertname := p.CommonLabels["alertname"] if alertname == "" && len(alerts) > 0 { alertname = alerts[0].Labels["alertname"] } // 颜色:FIRING + critical 用 red;warning 用 orange;resolved 用 green template := "blue" if strings.ToLower(p.Status) == "firing" { if sev == "critical" { template = "red" } else if sev == "warning" { template = "orange" } else { template = "blue" } } else { template = "green" } title := "[" + strings.ToUpper(p.Status) + "][" + sev + "] " + alertname + " (" + intToString(len(alerts)) + ")" // 内容用 markdown,最多展示前 5 条(避免卡片过长) maxShow := 5 show := alerts more := 0 if len(alerts) > maxShow { show = alerts[:maxShow] more = len(alerts) - maxShow } var md strings.Builder md.WriteString("**Receiver:** " + p.Receiver + "\n") if p.ExternalURL != "" { md.WriteString("**Alertmanager:** " + p.ExternalURL + "\n") } md.WriteString("\n") for i, a := range show { an := a.Labels["alertname"] inst := a.Labels["instance"] md.WriteString("**#" + intToString(i+1) + "** " + an) if inst != "" { md.WriteString(" @ `" + inst + "`") } md.WriteString("\n") if s := a.Annotations["summary"]; s != "" { md.WriteString("- **summary:** " + s + "\n") } if d := a.Annotations["description"]; d != "" { md.WriteString("- **desc:** " + d + "\n") } if a.StartsAt != "" { md.WriteString("- **startsAt:** " + a.StartsAt + "\n") } if a.GeneratorURL != "" { md.WriteString("- **url:** " + a.GeneratorURL + "\n") } md.WriteString("\n") } if more > 0 { md.WriteString("…还有 **" + intToString(more) + "** 条未展开\n") } // 如果有 generatorURL,就加一个按钮(取第一条有 url 的) btnURL := "" for _, a := range alerts { if a.GeneratorURL != "" { btnURL = a.GeneratorURL break } } elements := []interface{}{ map[string]interface{}{"tag": "markdown", "content": md.String()}, } if btnURL != "" { elements = append(elements, map[string]interface{}{"tag": "hr"}, map[string]interface{}{ "tag": "action", "actions": []interface{}{ map[string]interface{}{ "tag": "button", "text": map[string]interface{}{"tag": "plain_text", "content": "打开规则/图表"}, "type": "primary", "url": btnURL, }, }, }, ) } card := map[string]interface{}{ "config": map[string]interface{}{ "wide_screen_mode": true, }, "header": map[string]interface{}{ "title": map[string]interface{}{"tag": "plain_text", "content": title}, "template": template, }, "elements": elements, } return card } /* ============ 发送:重试 + 限流 ============ */ type httpError struct { code int body string } func (e *httpError) Error() string { if e.body != "" { return "http status " + intToString(e.code) + " body=" + e.body } return "http status " + intToString(e.code) } func isRetryableStatus(code int) bool { return code == 429 || code >= 500 } func doPost(ctx context.Context, client *http.Client, url string, payload []byte) error { req, _ := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(payload)) req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode/100 == 2 { return nil } // 读一点返回体,方便排查(最多 2KB) b, _ := io.ReadAll(io.LimitReader(resp.Body, 2048)) return &httpError{code: resp.StatusCode, body: strings.TrimSpace(string(b))} } func sendWithRetry(ctx context.Context, rl *RateLimiter, cfg Config, t Target, body FeishuBody) error { client := &http.Client{Timeout: cfg.SendTimeout} payload, _ := json.Marshal(body) r := rand.New(rand.NewSource(time.Now().UnixNano())) var lastErr error for i := 0; i < cfg.RetryMax; i++ { // 限流:每次尝试都要拿 token(避免重试时把飞书打爆) if err := rl.Acquire(ctx); err != nil { return err } err := doPost(ctx, client, t.Webhook, payload) if err == nil { return nil } lastErr = err // 只有可重试错误才重试 retry := false if he, ok := err.(*httpError); ok { retry = isRetryableStatus(he.code) } else { retry = true // 网络错误等 } if !retry || i == cfg.RetryMax-1 { break } // 退避:base * 2^i + jitter(0~100ms) sleep := cfg.RetryBase * time.Duration(1<<i) sleep += time.Duration(r.Intn(100)) * time.Millisecond select { case <-ctx.Done(): return ctx.Err() case <-time.After(sleep): } } return lastErr } func buildFeishuBody(cfg Config, sev string, p AMPayload, alerts []Alert, webhookSecret string) FeishuBody { ts := "" sign := "" if webhookSecret != "" { ts = int64ToString(time.Now().Unix()) sign = genFeishuSign(webhookSecret, ts) } if cfg.MsgType == "text" { return FeishuBody{ Timestamp: ts, Sign: sign, MsgType: "text", Content: map[string]interface{}{ "text": formatText(p, alerts), }, } } // card return FeishuBody{ Timestamp: ts, Sign: sign, MsgType: "interactive", Card: buildCard(p, sev, alerts), } } /* ============ helpers ============ */ func getEnvDefault(k, def string) string { v := strings.TrimSpace(os.Getenv(k)) if v == "" { return def } return v } func mustParseDuration(s string) time.Duration { d, err := time.ParseDuration(s) if err != nil { return 0 } return d } func mustParseInt(s string) int { n := 0 for _, ch := range s { if ch >= '0' && ch <= '9' { n = n*10 + int(ch-'0') } } if n == 0 { return 0 } return n } func mustParseFloat(s string) float64 { // 简易 parse:支持 "2" "2.5" var n, frac, div float64 div = 1 seenDot := false for _, ch := range s { if ch == '.' { seenDot = true continue } if ch < '0' || ch > '9' { continue } if !seenDot { n = n*10 + float64(ch-'0') } else { frac = frac*10 + float64(ch-'0') div *= 10 } } return n + frac/div } func intToString(x int) string { return int64ToString(int64(x)) } func int64ToString(x int64) string { if x == 0 { return "0" } neg := x < 0 if neg { x = -x } var buf [32]byte i := len(buf) for x > 0 { i-- buf[i] = byte('0' + x%10) x /= 10 } if neg { i-- buf[i] = '-' } return string(buf[i:]) } /* ============ main ============ */ func main() { log.SetFlags(log.LstdFlags | log.Lmicroseconds) cfg := loadConfig() deduper := NewDeduper(cfg.DedupTTL) rl := NewRateLimiter(cfg.RateQPS, cfg.RateBurst) http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) w.Write([]byte("ok")) }) http.HandleFunc("/alertmanager", func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { w.WriteHeader(405) return } var p AMPayload if err := json.NewDecoder(r.Body).Decode(&p); err != nil { log.Printf("decode failed: remote=%s err=%v", r.RemoteAddr, err) w.WriteHeader(400) w.Write([]byte(err.Error())) return } sev := getSeverity(p) log.Printf("recv webhook: remote=%s status=%s receiver=%s alerts=%d severity=%s alertname=%s", r.RemoteAddr, p.Status, p.Receiver, len(p.Alerts), sev, p.CommonLabels["alertname"]) // 去重(只对 firing 做,resolved 不去重,避免“恢复消息被吞”) alertsToSend := make([]Alert, 0, len(p.Alerts)) suppressed := 0 for _, a := range p.Alerts { if strings.ToLower(p.Status) == "firing" && cfg.DedupTTL > 0 { key := "firing:" + alertKey(a) if !deduper.Allow(key) { suppressed++ continue } } alertsToSend = append(alertsToSend, a) } if len(alertsToSend) == 0 { log.Printf("dedup suppressed all alerts: suppressed=%d total=%d", suppressed, len(p.Alerts)) w.WriteHeader(200) w.Write([]byte("ok")) return } targets := selectTargets(cfg, sev) if len(targets) == 0 { log.Printf("no targets configured for severity=%s", sev) w.WriteHeader(500) w.Write([]byte("no targets configured")) return } okCount := 0 failCount := 0 // 给本次请求一个总体 deadline(避免 handler 卡太久) ctx, cancel := context.WithTimeout(r.Context(), cfg.SendTimeout*time.Duration(cfg.RetryMax+1)) defer cancel() for _, t := range targets { body := buildFeishuBody(cfg, sev, p, alertsToSend, t.Secret) err := sendWithRetry(ctx, rl, cfg, t, body) if err != nil { log.Printf("send failed: group=%s target=%s err=%v", t.Name, t.Webhook, err) failCount++ continue } log.Printf("send ok: group=%s target=%s", t.Name, t.Webhook) okCount++ } log.Printf("send summary: ok=%d fail=%d targets=%d suppressed=%d severity=%s", okCount, failCount, len(targets), suppressed, sev) if okCount == 0 { w.WriteHeader(502) w.Write([]byte("failed")) return } w.WriteHeader(200) w.Write([]byte("ok")) }) addr := ":8080" log.Printf("listening on %s msgType=%s dedup=%s retryMax=%d rateQps=%.2f burst=%d", addr, cfg.MsgType, cfg.DedupTTL, cfg.RetryMax, cfg.RateQPS, cfg.RateBurst) log.Fatal(http.ListenAndServe(addr, nil)) } 二、构建部署docker build -t harbor.axzys.cn/monitoring/feishu-forwarder:0.1.0 . docker push harbor.axzys.cn/monitoring/feishu-forwarder:0.1.0 .cat feishu.yaml apiVersion: apps/v1 kind: Deployment metadata: name: feishu-forwarder namespace: monitoring spec: replicas: 1 selector: matchLabels: { app: feishu-forwarder } template: metadata: labels: { app: feishu-forwarder } spec: containers: - name: app image: harbor.axzys.cn/monitoring/feishu-forwarder:0.1.2 imagePullPolicy: Always ports: - containerPort: 8080 env: - name: FEISHU_WEBHOOKS_CRITICAL valueFrom: { secretKeyRef: { name: feishu-forwarder-secret, key: FEISHU_WEBHOOKS_CRITICAL } } - name: FEISHU_WEBHOOKS_WARNING valueFrom: { secretKeyRef: { name: feishu-forwarder-secret, key: FEISHU_WEBHOOKS_WARNING } } - name: FEISHU_WEBHOOKS_DEFAULT valueFrom: { secretKeyRef: { name: feishu-forwarder-secret, key: FEISHU_WEBHOOKS_DEFAULT } } - name: FEISHU_SECRET_CRITICAL valueFrom: { secretKeyRef: { name: feishu-forwarder-secret, key: FEISHU_SECRET_CRITICAL } } - name: FEISHU_SECRET_WARNING valueFrom: { secretKeyRef: { name: feishu-forwarder-secret, key: FEISHU_SECRET_WARNING } } - name: FEISHU_SECRET_DEFAULT valueFrom: { secretKeyRef: { name: feishu-forwarder-secret, key: FEISHU_SECRET_DEFAULT } } - name: FEISHU_MSG_TYPE value: "card" # card / text - name: DEDUP_TTL value: "10m" - name: RETRY_MAX value: "3" - name: RETRY_BASE value: "300ms" - name: RATE_QPS value: "2" - name: RATE_BURST value: "5" - name: SEND_TIMEOUT value: "6s" readinessProbe: httpGet: { path: /healthz, port: 8080 } initialDelaySeconds: 2 periodSeconds: 5 --- apiVersion: v1 kind: Service metadata: name: feishu-forwarder namespace: monitoring spec: selector: { app: feishu-forwarder } ports: - name: http port: 8080 targetPort: 8080 type: ClusterIP cat feishu-secret.yaml apiVersion: v1 kind: Secret metadata: name: feishu-forwarder-secret namespace: monitoring type: Opaque stringData: FEISHU_WEBHOOKS_CRITICAL: "https://open.feishu.cn/open-apis/bot/v2/hook/飞书token" FEISHU_WEBHOOKS_WARNING: "https://open.feishu.cn/open-apis/bot/v2/hook/飞书token" FEISHU_WEBHOOKS_DEFAULT: "https://open.feishu.cn/open-apis/bot/v2/hook/xxxx" # 如果你开了“签名校验”,不同群机器人 secret 往往不同 FEISHU_SECRET_CRITICAL: "SEC_xxx" FEISHU_SECRET_WARNING: "SEC_yyy" FEISHU_SECRET_DEFAULT: "SEC_zzz" cat alertmanagerConfig.yaml apiVersion: monitoring.coreos.com/v1alpha1 kind: AlertmanagerConfig metadata: name: feishu-forwarder namespace: monitoring labels: alertmanagerConfig: main # 这行是否需要,取决于你的 Alertmanager 选择器 spec: route: receiver: feishu-forwarder groupWait: 30s groupInterval: 5m repeatInterval: 30m receivers: - name: feishu-forwarder webhookConfigs: - url: http://feishu-forwarder.monitoring.svc:8080/alertmanager sendResolved: true root@k8s-01:/woke/prometheus/feishu# kubectl get pod -n monitoring NAME READY STATUS RESTARTS AGE alertmanager-main-0 2/2 Running 0 7d2h alertmanager-main-1 2/2 Running 0 7d2h alertmanager-main-2 2/2 Running 0 7d2h blackbox-exporter-7fcbd888d-zv6z6 3/3 Running 0 15d feishu-forwarder-8559bf6b68-njzvq 1/1 Running 0 68m grafana-7ff454c477-l9x2k 1/1 Running 0 15d kube-state-metrics-78f95f79bb-wpcln 3/3 Running 0 15d node-exporter-2vq26 2/2 Running 2 (35d ago) 39d node-exporter-622pm 2/2 Running 24 (35d ago) 39d node-exporter-rl67z 2/2 Running 22 (35d ago) 39d prometheus-adapter-585d9c5dd5-bfsxw 1/1 Running 0 8d prometheus-adapter-585d9c5dd5-pcrnd 1/1 Running 0 8d prometheus-k8s-0 2/2 Running 0 7d2h prometheus-k8s-1 2/2 Running 0 7d2h prometheus-operator-78967669c9-5pk25 2/2 Running 0 7d2h 三、调试 kubectl -n monitoring port-forward svc/alertmanager-main 19093:9093 kubectl -n monitoring logs -f deploy/feishu-forwarder curl -i -X POST http://127.0.0.1:19093/api/v2/alerts \ -H 'Content-Type: application/json' \ -d '[{ "labels":{"alertname":"axingWarning","severity":"warning","instance":"demo:9100","namespace":"monitoring"}, "annotations":{"summary":"injected warning","description":"from alertmanager api"}, "startsAt":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'" }]'操作过程中出现了 prometheus 已经告警 并且已经到Alertmanager了 但是 feishu-forwarder 没有收到 解决方法 是加上 不然他只会通知monitoring这个名称空间的告警信息 matchers: - name: prometheus value: monitoring/k8s 还有就是InfoInhibitor 一直刷屏通知告警 有两种解决方法 一、就是改上面的feishu-secret把FEISHU_WEBHOOKS_DEFAULT注释掉 还有一种就是下面这种只通知warning/critical root@k8s-01:/woke/prometheus/feishu# cat alertmanagerConfig.yaml apiVersion: monitoring.coreos.com/v1alpha1 kind: AlertmanagerConfig metadata: name: feishu-forwarder namespace: monitoring labels: alertmanagerConfig: main spec: route: receiver: feishu-forwarder groupWait: 30s groupInterval: 5m repeatInterval: 30m matchers: - name: prometheus value: monitoring/k8s matchType: "=" # 建议:只推 warning/critical,InfoInhibitor(severity=none) 就不会再刷飞书 - name: severity value: warning|critical matchType: "=~" receivers: - name: feishu-forwarder webhookConfigs: - url: http://feishu-forwarder.monitoring.svc:8080/alertmanager sendResolved: true
2026年02月05日
6 阅读
0 评论
0 点赞
2026-02-05
jenkins升级
一、升级最稳妥的 LTS 逐级升级(推荐) 先补齐本线最后一个补丁:2.516.3(把 2.516 线能拿到的修复先吃满) 升到下一条 LTS 基线:2.528.3(过渡 LTS 线) 升到当前在维护的 LTS:2.541.1(截至 2026-02-05 仍是主流 LTS) 这么做的好处:每一步跨度小,遇到插件/鉴权问题更容易定位;并且升级指南也建议如果跳 LTS,要把中间每段的升级注意事项都看一遍。root@k8s-01:/woke/jenkins# cat deployment.yaml # jenkins-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: jenkins namespace: jenkins spec: replicas: 1 selector: matchLabels: app: jenkins template: metadata: labels: app: jenkins spec: securityContext: fsGroup: 1000 serviceAccountName: jenkins-admin containers: - name: jenkins image: registry.cn-guangzhou.aliyuncs.com/xingcangku/jenkins-jenkins-lts-jdk17:lts-jdk17 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 - containerPort: 50000 # ★ JVM 参数 env: - name: JENKINS_JAVA_OPTIONS value: "-Djava.net.preferIPv4Stack=true" - name: JAVA_OPTS value: "-Djava.net.preferIPv4Stack=true" volumeMounts: - name: jenkins-data mountPath: /var/jenkins_home # ★ 新增挂载,把每个节点上的 /root/cicd 挂进 Jenkins 家目录 - name: cicd-tools mountPath: /var/jenkins_home/cicd resources: limits: cpu: "1" memory: "4Gi" requests: cpu: "0.5" memory: "1Gi" livenessProbe: httpGet: path: /login port: 8080 initialDelaySeconds: 90 periodSeconds: 10 volumes: - name: jenkins-data persistentVolumeClaim: claimName: jenkins-pvc # ★ 新增 volume,使用 hostPath 指向每个节点的 /root/cicd - name: cicd-tools hostPath: path: /root/cicd type: Directory # 如果想让 k8s 自动创建目录,也可以用: # type: DirectoryOrCreate
2026年02月05日
5 阅读
0 评论
0 点赞
2026-02-03
istio流量分析
一、流量走势NodePort → ingressgateway Service → ingressgateway Pod(Envoy) → Gateway 筛选 → VirtualService 路由 → productpage Service:9080 → productpage Pod #如果不是NodePort 就需要kubectl port-forward -n istio-system --address 0.0.0.0 svc/istio-ingressgateway 8080:80 进行端口暴露 只需要记住一点svc只是负责把流量转发到对应的pod 而网关和路由的匹配则是istio-ingressgateway进行处理二、对应的yaml文件cat gateway.yaml apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: bookinfo-gateway namespace: default spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" root@k8s-01:/woke/istio# kubectl get virtualservice bookinfo -n default -o yaml apiVersion: networking.istio.io/v1 kind: VirtualService metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"networking.istio.io/v1beta1","kind":"VirtualService","metadata":{"annotations":{},"name":"bookinfo","namespace":"default"},"spec":{"gateways":["bookinfo-gateway"],"hosts":["*"],"http":[{"match":[{"uri":{"prefix":"/"}}],"route":[{"destination":{"host":"productpage","port":{"number":9080}}}]}]}} creationTimestamp: "2025-12-31T05:30:04Z" generation: 1 name: bookinfo namespace: default resourceVersion: "8121204" uid: b0fd2c20-35ab-475c-8c1a-d6dc36749ce8 spec: gateways: - bookinfo-gateway hosts: - '*' http: - match: - uri: prefix: / route: - destination: host: productpage port: number: 9080三、对应svc和podroot@k8s-01:/woke/istio# kubectl get pod NAME READY STATUS RESTARTS AGE bookinfo-gateway-istio-6c4c8d9b74-z7c4j 1/1 Running 0 18d details-v1-7b88fb8889-5qt26 2/2 Running 0 33d nginx-5fd58574d-2c9z9 2/2 Running 0 13d nginx-test-78b8db46d6-cfd98 2/2 Running 0 13d productpage-v1-79d79d6-mktpd 2/2 Running 0 33d ratings-v1-5b89cf4bbf-c9xdg 2/2 Running 0 33d reviews-v1-ffd57b847-w9dkr 2/2 Running 0 33d reviews-v2-8cc6fd8dc-q9bd9 2/2 Running 0 33d reviews-v3-cf48455-znts5 2/2 Running 0 33d traefik-gw-istio-7867b4f544-hkknj 1/1 Running 0 18d root@k8s-01:/woke/istio# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE bookinfo-gateway-istio ClusterIP 10.105.38.228 <none> 15021/TCP,80/TCP 18d details ClusterIP 10.100.97.40 <none> 9080/TCP 35d kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 78d nginx ClusterIP 10.110.220.61 <none> 80/TCP 60d nginx-svc NodePort 10.108.4.45 <none> 80:32574/TCP 77d productpage ClusterIP 10.111.145.105 <none> 9080/TCP 35d ratings ClusterIP 10.98.94.10 <none> 9080/TCP 35d reviews ClusterIP 10.97.19.38 <none> 9080/TCP 35d traefik-gw-istio LoadBalancer 10.103.179.128 <pending> 15021:31055/TCP,8000:30447/TCP 18d root@k8s-01:/woke/istio# kubectl get pod -n istio-system NAME READY STATUS RESTARTS AGE istio-egressgateway-596f455c4f-7qh6w 1/1 Running 0 13d istio-ingressgateway-796f5cf647-tcpph 1/1 Running 0 13d istiod-5c84f8c79d-ddxkz 1/1 Running 0 13d kiali-68f9949bf5-8n4tk 1/1 Running 6 (13d ago) 13d prometheus-7f6bc65664-29c7c 0/2 Completed 0 18d prometheus-7f6bc65664-llp2q 2/2 Running 0 5d root@k8s-01:/woke/istio# kubectl get svc -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-egressgateway ClusterIP 10.106.183.187 <none> 80/TCP,443/TCP 35d istio-ingressgateway NodePort 10.99.189.246 <none> 15021:31689/TCP,80:32241/TCP,443:30394/TCP,31400:31664/TCP,15443:32466/TCP 35d istiod ClusterIP 10.104.189.5 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 35d istiod-revision-tag-default ClusterIP 10.102.152.242 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 35d kiali NodePort 10.103.234.52 <none> 20001:30318/TCP,9090:30682/TCP 34d prometheus ClusterIP 10.100.183.52 <none> 9090/TCP 34d root@k8s-01:/woke/istio#
2026年02月03日
11 阅读
0 评论
0 点赞
2026-01-29
问题
一、找回密码root@k8s-01:~# kubectl -n monitoring get pod | grep grafana grafana-7ff454c477-l9x2k 1/1 Running 0 8d root@k8s-01:~# kubectl -n monitoring exec -it grafana-7ff454c477-l9x2k -- sh /usr/share/grafana $ grafana-cli admin reset-admin-password '33070595Abc' Deprecation warning: The standalone 'grafana-cli' program is deprecated and will be removed in the future. Please update all uses of 'grafana-cli' to 'grafana cli' INFO [01-29|12:45:37] Starting Grafana logger=settings version= commit= branch= compiled=1970-01-01T00:00:00Z INFO [01-29|12:45:37] Config loaded from logger=settings file=/usr/share/grafana/conf/defaults.ini INFO [01-29|12:45:37] Config overridden from Environment variable logger=settings var="GF_PATHS_DATA=/var/lib/grafana" INFO [01-29|12:45:37] Config overridden from Environment variable logger=settings var="GF_PATHS_LOGS=/var/log/grafana" INFO [01-29|12:45:37] Config overridden from Environment variable logger=settings var="GF_PATHS_PLUGINS=/var/lib/grafana/plugins" INFO [01-29|12:45:37] Config overridden from Environment variable logger=settings var="GF_PATHS_PROVISIONING=/etc/grafana/provisioning" INFO [01-29|12:45:37] Target logger=settings target=[all] INFO [01-29|12:45:37] Path Home logger=settings path=/usr/share/grafana INFO [01-29|12:45:37] Path Data logger=settings path=/var/lib/grafana INFO [01-29|12:45:37] Path Logs logger=settings path=/var/log/grafana INFO [01-29|12:45:37] Path Plugins logger=settings path=/var/lib/grafana/plugins INFO [01-29|12:45:37] Path Provisioning logger=settings path=/etc/grafana/provisioning INFO [01-29|12:45:37] App mode production logger=settings INFO [01-29|12:45:37] FeatureToggles logger=featuremgmt recoveryThreshold=true panelMonitoring=true lokiQuerySplitting=true nestedFolders=true logsContextDatasourceUi=true cloudWatchNewLabelParsing=true logRowsPopoverMenu=true kubernetesPlaylists=true dataplaneFrontendFallback=true recordedQueriesMulti=true transformationsVariableSupport=true addFieldFromCalculationStatFunctions=true cloudWatchCrossAccountQuerying=true prometheusAzureOverrideAudience=true lokiQueryHints=true logsExploreTableVisualisation=true annotationPermissionUpdate=true lokiMetricDataplane=true prometheusMetricEncyclopedia=true lokiStructuredMetadata=true topnav=true alertingInsights=true exploreMetrics=true formatString=true ssoSettingsApi=true autoMigrateXYChartPanel=true tlsMemcached=true prometheusConfigOverhaulAuth=true logsInfiniteScrolling=true alertingSimplifiedRouting=true awsAsyncQueryCaching=true managedPluginsInstall=true cloudWatchRoundUpEndTime=true transformationsRedesign=true alertingNoDataErrorExecution=true dashgpt=true influxdbBackendMigration=true prometheusDataplane=true groupToNestedTableTransformation=true correlations=true publicDashboards=true angularDeprecationUI=true INFO [01-29|12:45:37] Connecting to DB logger=sqlstore dbtype=sqlite3 INFO [01-29|12:45:37] Locking database logger=migrator INFO [01-29|12:45:37] Starting DB migrations logger=migrator INFO [01-29|12:45:37] migrations completed logger=migrator performed=0 skipped=594 duration=359.617µs INFO [01-29|12:45:37] Unlocking database logger=migrator INFO [01-29|12:45:37] Envelope encryption state logger=secrets enabled=true current provider=secretKey.v1 Admin password changed successfully ✔ /usr/share/grafana $ exit root@k8s-01:~# cat <<'EOF' | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-traefik-to-grafana namespace: monitoring spec: podSelector: matchLabels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus policyTypes: ["Ingress"] ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: traefik ports: - protocol: TCP port: 3000 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-traefik-to-prometheus namespace: monitoring spec: podSelector: matchLabels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus policyTypes: ["Ingress"] ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: traefik ports: - protocol: TCP port: 9090 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-traefik-to-alertmanager namespace: monitoring spec: podSelector: matchLabels: app.kubernetes.io/component: alert-router app.kubernetes.io/instance: main app.kubernetes.io/name: alertmanager app.kubernetes.io/part-of: kube-prometheus policyTypes: ["Ingress"] ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: traefik ports: - protocol: TCP port: 9093 EOF 需要放行 monitoring 里原来的 NetworkPolicy 没放行 traefik → 导致 Traefik 转发到 grafana/prometheus/alertmanager 全部被丢包,最后表现成 504/超时。#添加节点 创建 additionalScrapeConfigs 的 Secret(把外部节点加进去) #我这里用 job_name: node-exporter 是为了让你现成的 Node Exporter / Nodes 仪表盘直接复用(很多面板按 job 过滤)。 cat <<'EOF' | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: prometheus-additional-scrape-configs namespace: monitoring type: Opaque stringData: additional-scrape-configs.yaml: | - job_name: node-exporter static_configs: - targets: - 192.168.1.12:9100 - 192.168.1.15:9100 - 192.168.1.30:9100 labels: origin: external relabel_configs: - source_labels: [__address__] target_label: instance regex: '([^:]+):\d+' replacement: '$1' EOF #把 Secret 挂到 Prometheus(prometheus-k8s) kubectl -n monitoring patch prometheus prometheus-k8s --type merge -p ' { "spec": { "additionalScrapeConfigs": { "name": "prometheus-additional-scrape-configs", "key": "additional-scrape-configs.yaml" } } }' #验证 kubectl -n monitoring port-forward svc/prometheus-k8s 9090:9090
2026年01月29日
9 阅读
0 评论
0 点赞
2026-01-27
F9P和DETA配置
一、F9P接线 F9P TX1 → DETA R3 F9P GND → DETA G #数据 05:39:17 $GNRMC,053917.00,A,2232.90388,N,11356.18681,E,0.101,,270126,,,A,V*10 05:39:17 $GNVTG,,T,,M,0.101,N,0.187,K,A*33 05:39:17 $GNGGA,053917.00,2232.90388,N,11356.18681,E,1,10,1.84,37.4,M,-2.7,M,,*62 05:39:17 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:17 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:17 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:17 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:17 $GPGSV,3,1,12,01,50,161,45,02,65,092,40,03,01,168,,04,12,190,25,1*6D 05:39:17 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,19,1*62 05:39:17 $GPGSV,3,3,12,16,12,088,19,17,12,243,27,27,14,044,19,30,31,318,,1*6D 05:39:17 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,18,6*61 05:39:17 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:17 $GPGSV,3,3,12,16,12,088,,17,12,243,25,27,14,044,,30,31,318,,6*68 05:39:17 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:17 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,17,1*75 05:39:17 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,21,74,35,346,,3*7D 05:39:17 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,19,3*72 05:39:17 $GAGSV,3,1,09,02,35,061,21,07,32,265,,08,27,205,13,15,32,176,28,7*78 05:39:17 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,45,7*76 05:39:17 $GAGSV,3,3,09,36,23,048,24,7*44 05:39:17 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:17 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,38,2*79 05:39:17 $GAGSV,3,3,09,36,23,048,,2*47 05:39:17 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:17 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:17 $GNGLL,2232.90388,N,11356.18681,E,053917.00,A,A*73 05:39:18 $GNRMC,053918.00,A,2232.90388,N,11356.18681,E,0.060,,270126,,,A,V*19 05:39:18 $GNVTG,,T,,M,0.060,N,0.111,K,A*3A 05:39:18 $GNGGA,053918.00,2232.90388,N,11356.18681,E,1,10,1.84,37.4,M,-2.7,M,,*6D 05:39:18 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:18 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:18 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:18 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:18 $GPGSV,3,1,12,01,50,161,45,02,65,092,40,03,01,168,,04,12,190,24,1*6C 05:39:18 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,17,1*6C 05:39:18 $GPGSV,3,3,12,16,12,088,19,17,12,243,27,27,14,044,18,30,31,318,,1*6C 05:39:18 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,18,6*61 05:39:18 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:18 $GPGSV,3,3,12,16,12,088,,17,12,243,25,27,14,044,,30,31,318,,6*68 05:39:18 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:18 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,16,1*74 05:39:18 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,22,74,35,346,,3*7E 05:39:18 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,20,3*78 05:39:18 $GAGSV,3,1,09,02,35,061,21,07,32,265,,08,27,205,13,15,32,176,28,7*78 05:39:18 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,45,7*76 05:39:18 $GAGSV,3,3,09,36,23,048,24,7*44 05:39:18 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:18 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,38,2*79 05:39:18 $GAGSV,3,3,09,36,23,048,,2*47 05:39:18 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:18 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:18 $GNGLL,2232.90388,N,11356.18681,E,053918.00,A,A*7C 05:39:19 $GNRMC,053919.00,A,2232.90387,N,11356.18682,E,0.055,,270126,,,A,V*12 05:39:19 $GNVTG,,T,,M,0.055,N,0.101,K,A*3D 05:39:19 $GNGGA,053919.00,2232.90387,N,11356.18682,E,1,11,1.84,37.4,M,-2.7,M,,*61 05:39:19 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:19 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:19 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:19 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:19 $GPGSV,3,1,12,01,50,161,45,02,65,092,40,03,01,168,,04,12,190,25,1*6D 05:39:19 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,16,1*6D 05:39:19 $GPGSV,3,3,12,16,12,088,20,17,12,243,,27,14,044,18,30,31,318,,1*63 05:39:19 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,17,6*6E 05:39:19 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:19 $GPGSV,3,3,12,16,12,088,,17,12,243,25,27,14,044,,30,31,318,,6*68 05:39:19 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:19 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,16,1*74 05:39:19 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,21,74,35,346,,3*7D 05:39:19 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,20,3*78 05:39:19 $GAGSV,3,1,09,02,35,061,21,07,32,265,,08,27,205,14,15,32,176,28,7*7F 05:39:19 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,45,7*76 05:39:19 $GAGSV,3,3,09,36,23,048,24,7*44 05:39:19 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:19 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,38,2*79 05:39:19 $GAGSV,3,3,09,36,23,048,,2*47 05:39:19 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:19 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:19 $GNGLL,2232.90387,N,11356.18682,E,053919.00,A,A*71 05:39:20 $GNRMC,053920.00,A,2232.90385,N,11356.18683,E,0.025,,270126,,,A,V*1C 05:39:20 $GNVTG,,T,,M,0.025,N,0.045,K,A*3B 05:39:20 $GNGGA,053920.00,2232.90385,N,11356.18683,E,1,11,1.84,37.4,M,-2.7,M,,*68 05:39:20 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:20 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:20 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:20 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:20 $GPGSV,3,1,12,01,50,161,45,02,65,092,40,03,01,168,,04,12,190,25,1*6D 05:39:20 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,15,1*6E 05:39:20 $GPGSV,3,3,12,16,12,088,20,17,12,243,,27,14,044,18,30,31,318,,1*63 05:39:20 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,17,6*6E 05:39:20 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:20 $GPGSV,3,3,12,16,12,088,,17,12,243,25,27,14,044,,30,31,318,,6*68 05:39:20 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,27,74,35,346,,1*79 05:39:20 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,14,1*76 05:39:20 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,21,74,35,346,,3*7D 05:39:20 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,20,3*78 05:39:20 $GAGSV,3,1,09,02,35,061,22,07,32,265,,08,27,205,15,15,32,176,28,7*7D 05:39:20 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,45,7*76 05:39:20 $GAGSV,3,3,09,36,23,048,24,7*44 05:39:20 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,32,2*72 05:39:20 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,38,2*79 05:39:20 $GAGSV,3,3,09,36,23,048,,2*47 05:39:20 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:20 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:20 $GNGLL,2232.90385,N,11356.18683,E,053920.00,A,A*78 05:39:21 $GNRMC,053921.00,A,2232.90383,N,11356.18684,E,0.031,,270126,,,A,V*19 05:39:21 $GNVTG,,T,,M,0.031,N,0.057,K,A*3D 05:39:21 $GNGGA,053921.00,2232.90383,N,11356.18684,E,1,11,1.84,37.4,M,-2.7,M,,*68 05:39:21 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:21 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:21 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:21 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:21 $GPGSV,3,1,12,01,50,161,45,02,65,092,39,03,01,168,,04,12,190,26,1*60 05:39:21 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,22,14,09,301,14,1*6F 05:39:21 $GPGSV,3,3,12,16,12,088,20,17,12,243,,27,14,044,18,30,31,318,,1*63 05:39:21 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,17,6*6E 05:39:21 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:21 $GPGSV,3,3,12,16,12,088,,17,12,243,25,27,14,044,,30,31,318,,6*68 05:39:21 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,27,74,35,346,,1*79 05:39:21 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,15,1*77 05:39:21 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,21,74,35,346,,3*7D 05:39:21 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,20,3*78 05:39:21 $GAGSV,3,1,09,02,35,061,22,07,32,265,,08,27,205,16,15,32,176,28,7*7E 05:39:21 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,45,7*76 05:39:21 $GAGSV,3,3,09,36,23,048,24,7*44 05:39:21 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:21 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,38,2*79 05:39:21 $GAGSV,3,3,09,36,23,048,,2*47 05:39:21 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:21 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:21 $GNGLL,2232.90383,N,11356.18684,E,053921.00,A,A*78 05:39:22 $GNRMC,053922.00,A,2232.90381,N,11356.18685,E,0.024,,270126,,,A,V*1D 05:39:22 $GNVTG,,T,,M,0.024,N,0.044,K,A*3B 05:39:22 $GNGGA,053922.00,2232.90381,N,11356.18685,E,1,11,1.84,37.5,M,-2.7,M,,*69 05:39:22 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:22 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:22 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:22 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:22 $GPGSV,3,1,12,01,50,161,45,02,65,092,39,03,01,168,,04,12,190,26,1*60 05:39:22 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,13,1*68 05:39:22 $GPGSV,3,3,12,16,12,088,20,17,12,243,29,27,14,044,18,30,31,318,,1*68 05:39:22 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,17,6*6E 05:39:22 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:22 $GPGSV,3,3,12,16,12,088,,17,12,243,26,27,14,044,,30,31,318,,6*6B 05:39:22 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,27,74,35,346,,1*79 05:39:22 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,16,1*74 05:39:22 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,21,74,35,346,,3*7D 05:39:22 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,20,3*78 05:39:22 $GAGSV,3,1,09,02,35,061,22,07,32,265,,08,27,205,17,15,32,176,29,7*7E 05:39:22 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,45,7*76 05:39:22 $GAGSV,3,3,09,36,23,048,24,7*44 05:39:22 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:22 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,38,2*79 05:39:22 $GAGSV,3,3,09,36,23,048,,2*47 05:39:22 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:22 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:22 $GNGLL,2232.90381,N,11356.18685,E,053922.00,A,A*78 05:39:23 $GNRMC,053923.00,A,2232.90378,N,11356.18687,E,0.026,,270126,,,A,V*1A 05:39:23 $GNVTG,,T,,M,0.026,N,0.048,K,A*35 05:39:23 $GNGGA,053923.00,2232.90378,N,11356.18687,E,1,11,1.84,37.6,M,-2.7,M,,*6F 05:39:23 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:23 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:23 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:23 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:23 $GPGSV,3,1,12,01,50,161,44,02,65,092,39,03,01,168,,04,12,190,25,1*62 05:39:23 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,17,1*6C 05:39:23 $GPGSV,3,3,12,16,12,088,21,17,12,243,28,27,14,044,17,30,31,318,,1*67 05:39:23 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,17,6*6E 05:39:23 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:23 $GPGSV,3,3,12,16,12,088,,17,12,243,26,27,14,044,,30,31,318,,6*6B 05:39:23 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,27,74,35,346,,1*79 05:39:23 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,16,1*74 05:39:23 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,22,74,35,346,,3*7E 05:39:23 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,20,3*78 05:39:23 $GAGSV,3,1,09,02,35,061,22,07,32,265,,08,27,205,16,15,32,176,29,7*7F 05:39:23 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,45,7*77 05:39:23 $GAGSV,3,3,09,36,23,048,23,7*43 05:39:23 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:23 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,38,2*78 05:39:23 $GAGSV,3,3,09,36,23,048,,2*47 05:39:23 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:23 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:23 $GNGLL,2232.90378,N,11356.18687,E,053923.00,A,A*7D 05:39:24 $GNRMC,053924.00,A,2232.90375,N,11356.18690,E,0.037,,270126,,,A,V*16 05:39:24 $GNVTG,,T,,M,0.037,N,0.068,K,A*37 05:39:24 $GNGGA,053924.00,2232.90375,N,11356.18690,E,1,11,1.84,37.8,M,-2.7,M,,*6D 05:39:24 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:24 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:24 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:24 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:24 $GPGSV,3,1,12,01,50,161,44,02,65,092,39,03,01,168,,04,12,190,25,1*62 05:39:24 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,19,1*62 05:39:24 $GPGSV,3,3,12,16,12,088,21,17,12,243,,27,14,044,17,30,31,318,,1*6D 05:39:24 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,16,6*6F 05:39:24 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:24 $GPGSV,3,3,12,16,12,088,,17,12,243,26,27,14,044,,30,31,318,,6*6B 05:39:24 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:24 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,15,1*77 05:39:24 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,22,74,35,346,,3*7E 05:39:24 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,19,3*72 05:39:24 $GAGSV,3,1,09,02,35,061,21,07,32,265,,08,27,205,16,15,32,176,29,7*7C 05:39:24 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,45,7*77 05:39:24 $GAGSV,3,3,09,36,23,048,23,7*43 05:39:24 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,32,2*72 05:39:24 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,38,2*78 05:39:24 $GAGSV,3,3,09,36,23,048,,2*47 05:39:24 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:24 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:24 $GNGLL,2232.90375,N,11356.18690,E,053924.00,A,A*71 05:39:25 $GNRMC,053925.00,A,2232.90374,N,11356.18691,E,0.048,,270126,,,A,V*1F 05:39:25 $GNVTG,,T,,M,0.048,N,0.090,K,A*38 05:39:25 $GNGGA,053925.00,2232.90374,N,11356.18691,E,1,11,1.84,37.8,M,-2.7,M,,*6C 05:39:25 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:25 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:25 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:25 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:25 $GPGSV,3,1,12,01,50,161,44,02,65,092,39,03,01,168,,04,12,190,25,1*62 05:39:25 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,19,1*62 05:39:25 $GPGSV,3,3,12,16,12,088,21,17,12,243,30,27,14,044,16,30,31,318,,1*6F 05:39:25 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,17,6*6E 05:39:25 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:25 $GPGSV,3,3,12,16,12,088,,17,12,243,26,27,14,044,,30,31,318,,6*6B 05:39:25 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:25 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,14,1*76 05:39:25 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,23,74,35,346,,3*7F 05:39:25 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,19,3*72 05:39:25 $GAGSV,3,1,09,02,35,061,22,07,32,265,,08,27,205,16,15,32,176,29,7*7F 05:39:25 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,45,7*77 05:39:25 $GAGSV,3,3,09,36,23,048,23,7*43 05:39:25 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:25 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,38,2*78 05:39:25 $GAGSV,3,3,09,36,23,048,,2*47 05:39:25 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:25 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:25 $GNGLL,2232.90374,N,11356.18691,E,053925.00,A,A*70 05:39:26 $GNRMC,053926.00,A,2232.90371,N,11356.18693,E,0.024,,270126,,,A,V*11 05:39:26 $GNVTG,,T,,M,0.024,N,0.045,K,A*3A 05:39:26 $GNGGA,053926.00,2232.90371,N,11356.18693,E,1,11,1.84,37.9,M,-2.7,M,,*69 05:39:26 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:26 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:26 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:26 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:26 $GPGSV,3,1,12,01,50,161,44,02,65,092,39,03,01,168,,04,12,190,25,1*62 05:39:26 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,18,1*63 05:39:26 $GPGSV,3,3,12,16,12,088,21,17,12,243,,27,14,044,14,30,31,318,,1*6E 05:39:26 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,17,6*6E 05:39:26 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:26 $GPGSV,3,3,12,16,12,088,,17,12,243,26,27,14,044,,30,31,318,,6*6B 05:39:26 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:26 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,13,1*71 05:39:26 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,23,74,35,346,,3*7F 05:39:26 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,19,3*72 05:39:26 $GAGSV,3,1,09,02,35,061,22,07,32,265,,08,27,205,16,15,32,176,29,7*7F 05:39:26 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,45,7*77 05:39:26 $GAGSV,3,3,09,36,23,048,23,7*43 05:39:26 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:26 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,38,2*78 05:39:26 $GAGSV,3,3,09,36,23,048,,2*47 05:39:26 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:26 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:26 $GNGLL,2232.90371,N,11356.18693,E,053926.00,A,A*74 05:39:27 $GNRMC,053927.00,A,2232.90370,N,11356.18692,E,0.048,,270126,,,A,V*1A 05:39:27 $GNVTG,,T,,M,0.048,N,0.089,K,A*30 05:39:27 $GNGGA,053927.00,2232.90370,N,11356.18692,E,1,11,1.84,37.9,M,-2.7,M,,*68 05:39:27 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:27 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:27 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:27 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:27 $GPGSV,3,1,12,01,50,161,44,02,65,092,39,03,01,168,,04,12,190,25,1*62 05:39:27 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,17,1*6C 05:39:27 $GPGSV,3,3,12,16,12,088,21,17,12,243,27,27,14,044,13,30,31,318,,1*6C 05:39:27 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,17,6*6E 05:39:27 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:27 $GPGSV,3,3,12,16,12,088,,17,12,243,26,27,14,044,,30,31,318,,6*6B 05:39:27 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:27 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,13,1*71 05:39:27 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,23,74,35,346,,3*7F 05:39:27 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,19,3*72 05:39:27 $GAGSV,3,1,09,02,35,061,22,07,32,265,,08,27,205,16,15,32,176,29,7*7F 05:39:27 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,45,7*77 05:39:27 $GAGSV,3,3,09,36,23,048,23,7*43 05:39:27 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:27 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,38,2*78 05:39:27 $GAGSV,3,3,09,36,23,048,,2*47 05:39:27 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:27 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:27 $GNGLL,2232.90370,N,11356.18692,E,053927.00,A,A*75 05:39:28 $GNRMC,053928.00,A,2232.90366,N,11356.18693,E,0.029,,270126,,,A,V*14 05:39:28 $GNVTG,,T,,M,0.029,N,0.054,K,A*37 05:39:28 $GNGGA,053928.00,2232.90366,N,11356.18693,E,1,11,1.84,38.0,M,-2.7,M,,*67 05:39:28 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:28 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:28 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:28 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:28 $GPGSV,3,1,12,01,50,161,44,02,65,092,39,03,01,168,,04,12,190,25,1*62 05:39:28 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,13,1*68 05:39:28 $GPGSV,3,3,12,16,12,088,21,17,12,243,30,27,14,044,12,30,31,318,,1*6B 05:39:28 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,16,6*6F 05:39:28 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:28 $GPGSV,3,3,12,16,12,088,,17,12,243,26,27,14,044,,30,31,318,,6*6B 05:39:28 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:28 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,14,1*76 05:39:28 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,23,74,35,346,,3*7F 05:39:28 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,19,3*72 05:39:28 $GAGSV,3,1,09,02,35,061,23,07,32,265,,08,27,205,16,15,32,176,29,7*7E 05:39:28 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,45,7*77 05:39:28 $GAGSV,3,3,09,36,23,048,22,7*42 05:39:28 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:28 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,38,2*78 05:39:28 $GAGSV,3,3,09,36,23,048,,2*47 05:39:28 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:28 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:28 $GNGLL,2232.90366,N,11356.18693,E,053928.00,A,A*7C 05:39:29 $GNRMC,053929.00,A,2232.90363,N,11356.18695,E,0.049,,270126,,,A,V*10 05:39:29 $GNVTG,,T,,M,0.049,N,0.091,K,A*38 05:39:29 $GNGGA,053929.00,2232.90363,N,11356.18695,E,1,11,1.84,38.1,M,-2.7,M,,*64 05:39:29 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:29 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:29 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:29 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:29 $GPGSV,3,1,12,01,50,161,44,02,65,092,39,03,01,168,,04,12,190,24,1*63 05:39:29 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,1*6A 05:39:29 $GPGSV,3,3,12,16,12,088,21,17,12,243,,27,14,044,13,30,31,318,,1*69 05:39:29 $GPGSV,3,1,12,01,50,161,32,02,65,092,,03,01,168,,04,12,190,17,6*6F 05:39:29 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:29 $GPGSV,3,3,12,16,12,088,,17,12,243,25,27,14,044,,30,31,318,,6*68 05:39:29 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:29 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,13,1*71 05:39:29 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,22,74,35,346,,3*7E 05:39:29 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,19,3*72 05:39:29 $GAGSV,3,1,09,02,35,061,23,07,32,265,,08,27,205,17,15,32,176,29,7*7F 05:39:29 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,45,7*77 05:39:29 $GAGSV,3,3,09,36,23,048,23,7*43 05:39:29 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:29 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,38,2*78 05:39:29 $GAGSV,3,3,09,36,23,048,,2*47 05:39:29 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:29 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:29 $GNGLL,2232.90363,N,11356.18695,E,053929.00,A,A*7E 05:39:30 $GNRMC,053930.00,A,2232.90362,N,11356.18695,E,0.037,,270126,,,A,V*10 05:39:30 $GNVTG,,T,,M,0.037,N,0.068,K,A*37 05:39:30 $GNGGA,053930.00,2232.90362,N,11356.18695,E,1,11,1.84,38.1,M,-2.7,M,,*6D 05:39:30 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:30 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:30 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:30 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:30 $GPGSV,3,1,12,01,50,161,44,02,65,092,39,03,01,168,,04,12,190,25,1*62 05:39:30 $GPGSV,3,2,12,07,61,311,,08,42,027,20,09,21,220,,14,09,301,,1*68 05:39:30 $GPGSV,3,3,12,16,12,088,22,17,12,243,27,27,14,044,14,30,31,318,,1*68 05:39:30 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,17,6*6E 05:39:30 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:30 $GPGSV,3,3,12,16,12,088,,17,12,243,25,27,14,044,,30,31,318,,6*68 05:39:30 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:30 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,10,1*72 05:39:30 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,22,74,35,346,,3*7E 05:39:30 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,19,3*72 05:39:30 $GAGSV,3,1,09,02,35,061,23,07,32,265,,08,27,205,17,15,32,176,29,7*7F 05:39:30 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,45,7*77 05:39:30 $GAGSV,3,3,09,36,23,048,23,7*43 05:39:30 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:30 $GAGSV,3,2,09,27,17,300,,29,07,312,,30,48,348,,34,54,106,38,2*78 05:39:30 $GAGSV,3,3,09,36,23,048,,2*47 05:39:30 $GBGSV,1,1,01,16,83,126,40,1*4A 05:39:30 $GBGSV,1,1,01,16,83,126,34,3*4B 05:39:30 $GNGLL,2232.90362,N,11356.18695,E,053930.00,A,A*77 时间:053917.00 ~ 053930.00 是 UTC 时间(NMEA 默认 UTC)。对应北京时间/中国时区 +8 大概是 13:39:17 ~ 13:39:30。 270126 年月日 定位状态:A(有效定位) 定位类型:GNGGA ... ,1,... → Fix Quality = 1(普通单点定位) 速度:0.02~0.10 knot(≈ 0.04~0.19 km/h)→ 基本静止,只有噪声抖动。 位置(十进制度): 纬度 2232.90388N → 22.548398°N 经度 11356.18681E → 113.9364468°E 13 秒内的漂移:从第一条到最后一条位置变化约 0.54 m(很像静止情况下的正常抖动/多路径)。 因为是静态环境所以准确A. $GNRMC(Recommended Minimum:最小定位信息) 例子: $GNRMC,053917.00,A,2232.90388,N,11356.18681,E,0.101,,270126,,,A,V*10 字段重点: 053917.00:UTC 时间 hhmmss.ss A:定位有效(V=无效) 2232.90388,N / 11356.18681,E:纬经度(ddmm.mmmmm 格式) 0.101:对地速度 knots 航向(course)这里是空的:你速度太低时很多设备会不输出航向 270126:日期 ddmmyy 倒数第二个 A:一般是 Mode=Autonomous(自主定位、无差分) 最后一个 V:这是 NMEA 新版本里扩展的 “Nav status/Integrity” 一类字段,F9P 有时会给 V(常见含义是“没有完整性信息/不可用”之类)。不影响你前面的 A 有效定位结论,但它提示:这不是带完整性监测/认证的导航状态输出。B. $GNVTG(Course/Speed:航向与速度) 例子:$GNVTG,,T,,M,0.101,N,0.187,K,A*33 真航向/磁航向都空(同样因为几乎不动) 0.101,N:0.101 knot 0.187,K:0.187 km/h A:模式 AutonomousC. $GNGGA(Fix Data:定位解算质量、卫星数、高度等) 例子:$GNGGA,053917.00,...,1,10,1.84,37.4,M,-2.7,M,,*62 关键字段: 1:Fix Quality = 1 单点定位(不是 RTK) 10/11:参与解算的卫星数(你这段里从 10 变到 11) 1.84:HDOP(水平几何精度因子,越小越好;1.84 属于“还行但不算很漂亮”) 37.4,M:海拔高度(通常是 相对大地水准面 MSL) -2.7,M:大地水准面起伏(Geoid separation) N ≈ -2.7 m 所以椭球高大概:h = H + N ≈ 37.4 + (-2.7) = 34.7 m(这段高度范围大概 34.7~35.4m 椭球高) 差分龄期/差分站号为空:没有差分改正输入 你这 13 秒里海拔从 37.4 → 38.1 m,静止情况下这种 0.7 m 级别上下浮动也挺常见(多路径/卫星几何变化/滤波)。D. $GNGSA(DOP + Used SVs:参与解算的卫星列表 + PDOP/HDOP/VDOP) 你有多条 GSA(这是 F9P 多星座输出时常见的写法),例如: ... 01,02,04,17 ...(GPS用到的) ... 84,85,73 ...(GLONASS用到的) ... 15,34,08 ...(Galileo用到的) ... 16 ...(北斗用到的) 末尾这三个是核心: PDOP 2.70 HDOP 1.84 VDOP 1.97 解释: PDOP 2.70:整体几何一般(天空开阔时经常能做到 1.x 甚至更低;你这里可能有遮挡/仰角截止较高/或解算策略没把更多卫星纳入) HDOP/VDOP 与 GGA 中一致E. $GxGSV(Satellites in View:可见卫星、方位、仰角、信噪比) 你这里有: $GPGSV:GPS(你这里显示 12 颗在视野) $GLGSV:GLONASS(8 颗) $GAGSV:Galileo(9 颗) $GBGSV:北斗(1 颗) GSV 每颗卫星给: PRN(卫星号) Elevation(仰角,0~90°) Azimuth(方位角,0~359°) SNR/CN0(信噪比,数字越大越强;空值通常表示该信号此刻没给出或不可用) 你还会看到同一星座的 GSV 重复两套,并且在校验和前多了一个类似 ...,1*xx 或 ...,6*xx 的尾字段: 这通常表示 Signal ID(不同频点/信号类型) F9P 是双频多星座,所以经常会把“同一颗卫星在不同信号上的 CN0”分别输出两套(例如 GPS L1 vs L2、Galileo E1 vs E5b、北斗 B1 vs B2 等)。 从你截取的 CN0 看,强信号里比较典型的有: GPS:PRN01(45)、PRN02(40)这类不错 GLONASS:PRN84(39)较强 Galileo:PRN34(45)很强 北斗:PRN16(40)且仰角 83°(几乎头顶),很稳F. $GNGLL(Geographic Position:经纬度简版) 例子:$GNGLL,2232.90388,N,11356.18681,E,053917.00,A,A*73 本质上是 RMC/GGA 的经纬度再输出一遍(更简洁)。 A,A:一个是数据有效,一个是模式(通常 Autonomous)
2026年01月27日
3 阅读
0 评论
0 点赞
1
2
3
...
31