Lorawan-stack: 1つの形式からの複数の結果メッセージをサポートする

作成日 2019年08月13日  ·  12コメント  ·  ソース: TheThingsNetwork/lorawan-stack

概要

1つのttnpb.ApplicationUpは、1つだけではなく、複数のフロントエンドメッセージを生成できるはずです。

なぜ私たちはこれが必要なのですか?

現在、1つのttnpb.ApplicationUpは1つのバイトスライスにマーシャリングされ、1つのフロントエンドメッセージ(1つのHTTP呼び出し、1つのMQTTメッセージなど)になります。 ただし、アップリンクのペイロードに複数の測定値が含まれている場合(1つのデバイスに複数のセンサーが接続されていると考えてください)、特定の形式で測定値ごとに複数のメッセージを作成できるようにすると便利です。

すでに何がありますか? あなたは今何を見ていますか?

https://github.com/TheThingsNetwork/lorawan-stack/blob/9112dd7bcd3f1f03190055542908b427b27acd1c/pkg/applicationserver/io/formatters/formatter.go#L23
この形式は現在、フロントエンドに送信されるメッセージを1つだけ返します。

何が欠けている? あなたは何が見たいですか?

結果を[]byteから[][]byteに変更する必要があります。

環境

93ea01b4b5af2672da5883b570be825a54b8afc1

これをどのように実装することを提案しますか?

Formatインターフェースを変更します。 その後、各フロントエンドを変更して、1つだけではなくすべてのメッセージを送信する必要があります。

これを自分で行い、プルリクエストを送信できますか?

はい、でもこれはコミュニティにお任せします。

application server needtriage

全てのコメント12件

@adriansmares私は現在この問題に取り組んでいます。 formatter.goファイルの* ttnpb.ApplicationUp関数の[] byteから[] [] byteに変更した後、json.goファイルとprotobuf.goファイルでも変更しました。 しかし今、それは次のエラーを出します:
image
親切にいくつかの提案を提供します。 ありがとうございました。

@ mihirr93現在、結果のスライス(各結果はバイトのスライス)を返すように呼び出しサイトを変更しているため、1つの結果のみが返される場所を[][]byte{ slice-containing-result }ラップする必要があります。

こんにちは@adriansmaresさん。 私たちのアプローチに関して少し混乱しています。 フロントエンドメッセージ(生のペイロード)を複数のメッセージにスライスすることにしています。 ただし、この場合、メッセージがスライスされるポイントは、そのエンコーディング(Cayenneまたはカスタムエンコーディング)によって異なりますが、これは不明です。 したがって、これを行うには、デコードされたペイロードを使用する必要があります。 ユーザーがTTNのペイロード形式タブにデコーダーを入力すると、アプリケーションは実際にデコードされた値をJSONで表示します(図を参照)。 このデコードされたペイロードを直接分割し、httpを使用してさらにプッシュするべきではありませんか?
image
この混乱に光を当てていただけませんか。
また、pkgファイルを変更するだけで、.protoファイルが自動的に更新されますか?
何卒よろしくお願い申し上げます。

_このリポジトリにはLoRaWANスタックのV3バージョンが含まれており、提供されている画像はV2バージョンを実行するTTNからのものであることに注意してください。_

この問題は、1つのメッセージから複数のペイロードを生成するためのサポートのみを扱っていることに注意してください。おそらく関心のある新しい形式の問題は、

それでも、この場合は、 JSON形式に基づく新しい形式を導入することをお勧めします。この形式では、アップリンク内で見つかったデコードされた情報に基づいて複数のペイロードが生成されます。
DecodedPayloadフィールドの一部として関心のあるフィールドが含まれているため、 ApplicationUp_UplinkMessageアップリンクメッセージを具体的に処理することをお勧めします。

このユースケースでは、protoファイルを変更する必要はありません。

私はまだスタックの内部動作とコードを理解しようとしています。 現在、私はこの問題のみに焦点を当てており、#1158には焦点を当てていません。 ApplicationUp_Uplinkmessageを変更することを提案したように、私はそれを理解しようとしています。 現在、次のクエリがあります。
1)構造体ApplicationUplinkと関数ApplicationUp_UplinkMessageは、ttnpbディレクトリのmessages.pb.goファイルで定義されています。 ただし、ファイルのヘッダーには「編集しないでください」と記載されています。 私はそれを無視すべきですか? またはそれを変更するための代替アプローチはありますか?
2)「 introduce a new format, based on the JSON one 」について詳しく教えてください。 新しいフォーマットを作成するのではなく、既存のフォーマットを変更するだけでよいと思いました。
3)1つの結果のみが返される結果のラッピングについても言及されました。 それは正確に何をしますか? 複数のメッセージを1つに再結合して、1つの結果だけを返しますか? そして、アップリンクメッセージに対してのみそれを行う必要がありますか?

[継続的な指導をありがとう@adriansmares 。 私はgolangチュートリアルを受講しましたが、これはGO言語との最初の対話であり、多くの疑問を抱えてご迷惑をおかけしましたことをお許しください]

  • そのファイルや*.pb.*ファイルを編集する必要はありません。 これらは、 mage proto:allを実行すると、 *.protoファイルから自動的に生成されます。 それにもかかわらず、この問題の目的のために、そのような変更を行う必要はありません。
  • 他の号でフォローアップしてください。
  • ラッピングの提案により、既存のコードをそのまま維持できます(1つのアップリンクメッセージから投稿される1つのペイロードを引き続き返します)。

パイプライン全体をよりよく説明しようとしましょう。これにより、これがどのように機能するかが明らかになるかもしれません。

  1. デバイスは1つのアップリンクを送信します。
  2. 1つのアップリンクはゲートウェイによって受信され、ゲートウェイサーバーに送信されます。ゲートウェイサーバーはそれをネットワークサーバーに転送し、ネットワークサーバーはアプリケーションサーバーに転送します。 ASに到達するメッセージは、タイプ*ttnpb.ApplicationUplinkです。
  3. ASはこの1つのアップリンクを取得し、デバイスペイロードフォーマッタを使用して、バイナリペイロードをデコードされたフィールドにデコードしようとします( FRMPayloadフィールドのバイトをDecodedPayloadのデコードされた構造に変換します)。
  4. 次に、それを*ttnpb.ApplicationUpラップし、フロントエンド(MQTT、webhook、PubSub、アプリケーションパッケージ)に送信します。
  5. フロントエンドはこの1 *ttnpb.ApplicationUpを受け取り、設定(フォーマット)に基づいて、使用するフォーマッターを選択します(フォーマッターインターフェイスはpkg/applicationserver/io/formatters定義されています)。
  6. フロントエンドは1 *ttnph.ApplicationUpformatter.FromUpを呼び出し、1つのメッセージの本文を表すバイトのスライス( []byte )を受け取ります。

さて、この問題に関しては、ステップ6だけを変更する必要があることがわかるといいのですが。

  • FromUpが複数のペイロード(バイトのスライスのスライス)を返すことができるように、インターフェイスと実装の両方の戻りタイプを変更します。
  • 既存のProtobufおよびJSON形式は動作を変更しないため、引き続き1つのペイロードのみを返す必要があります(そのため、ラップが必要です)。
  • これら2つ(インターフェースとフォーマッター)を変更して[][]byteを返すと、エラーが発生し始めます( FromUpを呼び出す場所のほとんどは、受信されるペイロードが1つだけであると想定しているため、更新する必要があります)これらの呼び出しサイトは、ペイロードのリストをループして、それぞれを送信します。

動作をまったく変更しないこの問題が修正された後でのみ、測定ごとに1つずつ、複数のペイロードのスライスを返す独自のフォーマッターの実装に進むことができます(ただし、この新しいフォーマットに注意してください)この問題の範囲外です!)。

あなたのような詳細、について説明し、ガイドのためにそんなに@adriansmaresをありがとうございます。 私は今、この問題をなんとか解決できたと思います。 また、 ./mage go:test js:test jsSDK:testテストしましたが、エラーは発生しません。 コードに加えられた主な変更は、以下に強調表示されています。
formatter.go

type Formatter interface {
    FromUp(*ttnpb.ApplicationUp) ([][]byte, error)
    ToDownlinks([]byte) (*ttnpb.ApplicationDownlinks, error)
    ToDownlinkQueueRequest([]byte) (*ttnpb.DownlinkQueueRequest, error)
}

json.go

func (json) FromUp(msg *ttnpb.ApplicationUp) ([][]byte, error) {
    m, e := jsonpb.TTN().Marshal(msg)
    return [][]byte{m}, e
}

protobuf.go
同上

mqtt.go

buf, err := c.format.FromUp(up.ApplicationUp)
                if err != nil {
                    logger.WithError(err).Warn("Failed to marshal upstream message")
                    continue
                }
                logger.Debug("Publish upstream message")
                for _, v := range buf {
                    c.session.Publish(&packet.PublishPacket{
                        TopicName:  topic.Join(topicParts),
                        TopicParts: topicParts,
                        QoS:        qosUpstream,
                        Message:    v,
                    })
                }

pubsub.go
同上

webhooks.go

unc (w *webhooks) newRequest(ctx context.Context, msg *ttnpb.ApplicationUp, hook *ttnpb.ApplicationWebhook) ([]*http.Request, error) {
    var cfg *ttnpb.ApplicationWebhook_Message
    switch msg.Up.(type) {
    case *ttnpb.ApplicationUp_UplinkMessage:
        cfg = hook.UplinkMessage
    case *ttnpb.ApplicationUp_JoinAccept:
        cfg = hook.JoinAccept
    case *ttnpb.ApplicationUp_DownlinkAck:
        cfg = hook.DownlinkAck
    case *ttnpb.ApplicationUp_DownlinkNack:
        cfg = hook.DownlinkNack
    case *ttnpb.ApplicationUp_DownlinkSent:
        cfg = hook.DownlinkSent
    case *ttnpb.ApplicationUp_DownlinkFailed:
        cfg = hook.DownlinkFailed
    case *ttnpb.ApplicationUp_DownlinkQueued:
        cfg = hook.DownlinkQueued
    case *ttnpb.ApplicationUp_LocationSolved:
        cfg = hook.LocationSolved
    }
    if cfg == nil {
        return nil, nil
    }
    url, err := url.Parse(hook.BaseURL)
    if err != nil {
        return nil, err
    }
    url.Path = path.Join(url.Path, cfg.Path)
    expandVariables(url, msg)
    if err != nil {
        return nil, err
    }
    format, ok := formats[hook.Format]
    if !ok {
        return nil, errFormatNotFound.WithAttributes("format", hook.Format)
    }
    buf, err := format.FromUp(msg)
    if err != nil {
        return nil, err
    }
    var requests []*http.Request
    for i, v := range buf {
        req, err := http.NewRequest(http.MethodPost, url.String(), bytes.NewReader(v))
        requests[i] = req
        if err != nil {
            return nil, err
        }
        for key, value := range hook.Headers {
            req.Header.Set(key, value)
        }
        if hook.DownlinkAPIKey != "" {
            req.Header.Set(downlinkKeyHeader, hook.DownlinkAPIKey)
            req.Header.Set(downlinkPushHeader, w.createDownlinkURL(ctx, hook.ApplicationWebhookIdentifiers, msg.EndDeviceIdentifiers, "push"))
            req.Header.Set(downlinkReplaceHeader, w.createDownlinkURL(ctx, hook.ApplicationWebhookIdentifiers, msg.EndDeviceIdentifiers, "replace"))
        }
        req.Header.Set("Content-Type", format.ContentType)
        req.Header.Set("User-Agent", userAgent)
    }
    return requests, nil
}

フィードバックやコメントをお寄せください。 タスクが完全に終了したら、コードスタイルのガイドラインに従って修正(Varの命名、インデントなど)を行います。 そして、これが正しければ、問題#1158についてさらに案内していただけませんか。 改めてありがとうございました。

@ mihirr93はよさそうだ! 変更をコミットして、この問題のプルリクエストを送信してください。 マージした後、#1158で説明した新しいフォーマッタに進むことができます。

@adriansmares確かに、私はそれをします。 そのプルリクエストは、前述の環境または最新バージョンのスタックに基づいている必要がありますか?

後で競合を回避するために、最新のmasterに基づいて変更をリベースすることをお勧めします。

この問題はかなり長い間非アクティブになっているので、トリアージに戻して、これに対する需要がまだあるかどうか、または単に削除する必要があるかどうかを確認しましょう。

スケーリングが不十分なため、これは不要になりました。

このページは役に立ちましたか?
0 / 5 - 0 評価