ํ๋์ ttnpb.ApplicationUp
๋ ํ๋๊ฐ ์๋ ์ฌ๋ฌ ํ๋ฐํธ ์๋ ๋ฉ์์ง๋ฅผ ์์ฑํ ์ ์์ด์ผ ํฉ๋๋ค.
ํ์ฌ, ํ๋์ ttnpb.ApplicationUp
๋ ํ๋์ ํ๋ฐํธ ์๋ ๋ฉ์์ง(ํ๋์ HTTP ํธ์ถ, ํ๋์ MQTT ๋ฉ์์ง ๋ฑ)๋ก ์ด์ด์ง๋ ํ๋์ ๋ฐ์ดํธ ์ฌ๋ผ์ด์ค๋ก๋ง ๋ง์ฌ๋ง๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์
๋งํฌ์ ํ์ด๋ก๋์ ์ฌ๋ฌ ์ธก์ ๊ฐ์ด ํฌํจ๋ ๊ฒฝ์ฐ(ํ๋์ ์ฅ์น์ ์ฐ๊ฒฐ๋ ์ฌ๋ฌ ์ผ์๋ฅผ ์๊ฐํด ๋ณด์ญ์์ค) ํน์ ํ์์ด ๊ฐ ์ธก์ ๊ฐ์ ๋ํด ์ฌ๋ฌ ๋ฉ์์ง๋ฅผ ์์ฑํ๋๋ก ํ์ฉํ๋ ๊ฒ์ด ๋์์ด ๋ ๊ฒ์
๋๋ค.
https://github.com/TheThingsNetwork/lorawan-stack/blob/9112dd7bcd3f1f03190055542908b427b27acd1c/pkg/applicationserver/io/formatters/formatter.go#L23
์ด ํ์์ ํ์ฌ ํ๋ฐํธ ์๋๋ก ๋ณด๋ผ ๋ฉ์์ง๋ฅผ ํ๋๋ง ๋ฐํํฉ๋๋ค.
๊ฒฐ๊ณผ๋ []byte
์์ [][]byte
๋ก ๋ณ๊ฒฝ๋์ด์ผ ํฉ๋๋ค.
93ea01b4b5af2672da5883b570be825a54b8afc1
Format
์ธํฐํ์ด์ค๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค. ๊ทธ ํ ๊ฐ ํ๋ฐํธ ์๋๋ ํ๋๊ฐ ์๋ ๋ชจ๋ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋๋ก ๋ณ๊ฒฝ๋์ด์ผ ํฉ๋๋ค.
[]http.Request
๋์ http.Request
) ์ด๋ฌํ ์์ฒญ์ ์์ฑํ๋ ๋ฐ format.FromUp
์ ๊ฒฐ๊ณผ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.topic.Send
์ ๊ฐ ๊ฒฐ๊ณผ์ ๋ํด i.format.FromUp
ํฉ๋๋ค.[][]byte
๋ก ๋ํํฉ๋๋ค.๋ค, ํ์ง๋ง ์ปค๋ฎค๋ํฐ์ ๋จ๊ฒจ๋๊ฒ ์ต๋๋ค.
@adriansmares ์ ๋ ํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋
ธ๋ ฅํ๊ณ ์์ต๋๋ค. formatter.go ํ์ผ์์ *ttnpb.ApplicationUp ํจ์๋ฅผ []byte์์ [][]byte๋ก ๋ณ๊ฒฝํ ํ json.go ๋ฐ protobuf.go ํ์ผ์์๋ ๋ณ๊ฒฝํ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด์ ๋ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
์น์ ํ๊ฒ ๋ช ๊ฐ์ง ์ ์์ ์ ๊ณตํฉ๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
@mihirr93 ์ด์ ๊ฒฐ๊ณผ ์กฐ๊ฐ(๊ฐ ๊ฒฐ๊ณผ๋ ๋ฐ์ดํธ ์กฐ๊ฐ์)์ ๋ฐํํ๋๋ก ํธ์ถ ์ฌ์ดํธ๋ฅผ ์์ ํ๊ณ ์์ผ๋ฏ๋ก [][]byte{ slice-containing-result }
๋ก ํ๋์ ๊ฒฐ๊ณผ๋ง ๋ฐํ๋๋ ์์น๋ฅผ ๋ํํด์ผ ํฉ๋๋ค.
์๋
ํ์ธ์ Mr. @adriansmares ์
๋๋ค. ๋๋ ์ฐ๋ฆฌ์ ์ ๊ทผ ๋ฐฉ์์ ๋ํด ์ฝ๊ฐ ํผ๋ ์ค๋ฝ์ต๋๋ค. ์ฐ๋ฆฌ๋ ํ๋ก ํธ ์๋ ๋ฉ์์ง(์์ ํ์ด๋ก๋)๋ฅผ ์ฌ๋ฌ ๋ฉ์์ง๋ก ๋ถํ ํ๋๋ก ๋ฌถ๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด ๊ฒฝ์ฐ ๋ฉ์์ง๊ฐ ์ฌ๋ผ์ด์ฑ๋๋ ์ง์ ์ ์ฐ๋ฆฌ์๊ฒ ์๋ ค์ง์ง ์์ ์ธ์ฝ๋ฉ(์นด์ด์ ๋๋ ์ฌ์ฉ์ ์ ์ ์ธ์ฝ๋ฉ)์ ๋ฐ๋ผ ๋ค๋ฆ
๋๋ค. ๋ฐ๋ผ์ ์ด๋ฅผ ์ํํ๋ ค๋ฉด ๋์ฝ๋ฉ๋ ํ์ด๋ก๋๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์ฌ์ฉ์๊ฐ TTN์ ํ์ด๋ก๋ ํ์ ํญ์ ๋์ฝ๋๋ฅผ ์
๋ ฅํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์ ๋ก ๋์ฝ๋ฉ๋ ๊ฐ์ JSON์ผ๋ก ํ์ํฉ๋๋ค(๊ทธ๋ฆผ ์ฐธ์กฐ). ์ด ๋์ฝ๋ฉ๋ ํ์ด๋ก๋๋ฅผ ์ง์ ๋ถํ ํ๊ณ http๋ฅผ ์ฌ์ฉํ์ฌ ์ถ๊ฐ๋ก ํธ์ํด์ผ ํ์ง ์์ต๋๊น?
์ด ํผ๋์ ๋ํด ์กฐ๊ธ์ด๋๋ง ์กฐ๋ช
ํด ์ฃผ์๊ฒ ์ต๋๊น?
๊ทธ๋ฆฌ๊ณ pkg ํ์ผ๋ง ์์ ํ๋ฉด .proto ํ์ผ์ด ์๋์ผ๋ก ์
๋ฐ์ดํธ๋ฉ๋๊น?
๊ทํ์ ์น์ ํ ์ง์๊ณผ ์๊ฐ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
_์ด ์ ์ฅ์์๋ LoRaWAN ์คํ์ V3 ๋ฒ์ ์ด ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ๊ณต๋ ์ฌ์ง์ V2 ๋ฒ์ ์ ์คํํ๋ TTN์์ ๊ฐ์ ธ์จ ๊ฒ์ ๋๋ค._
์ด ๋ฌธ์ ๋ ํ๋์ ๋ฉ์์ง์์ ์ฌ๋ฌ ํ์ด๋ก๋ ์์ฑ์ ๋ํ ์ง์๋ง ๋ค๋ฃจ๊ณ ์์ผ๋ฉฐ ๊ด์ฌ์ด ์์ ์ ์๋ ์๋ก์ด ํ์ ๋ฌธ์ ๋ https://github.com/TheThingsNetwork/lorawan-stack/issues/1158์ ๋๋ค. ์ด ๋ฌธ์ ๊ฐ ์ค์ ๋ก ์ฐพ๊ณ ์๋ ๋ฌธ์ ์ธ์ง ํ์ธํ์ญ์์ค.
๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ์ด ๊ฒฝ์ฐ ์
๋งํฌ ๋ด๋ถ์์ ๋ฐ๊ฒฌ๋ ๋์ฝ๋ฉ๋ ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฌ๋ฌ ํ์ด๋ก๋๋ฅผ ์์ฑํ๋ JSON ํ์์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ์๋ก์ด ํ์์ ๋์
ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
DecodedPayload
ํ๋์ ์ผ๋ถ๋ก ๊ด์ฌ ์๋ ํ๋๊ฐ ํฌํจ๋์ด ์์ผ๋ฏ๋ก ApplicationUp_UplinkMessage
์
๋งํฌ ๋ฉ์์ง๋ฅผ ๊ตฌ์ฒด์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ด ์ฌ์ฉ ์ฌ๋ก์ ๋ํด proto ํ์ผ์ ์์ ํ ํ์๊ฐ ์์ต๋๋ค.
๋๋ ์ฌ์ ํ ์คํ์ ๋ด๋ถ ์์
๊ณผ ์ฝ๋๋ฅผ ์ดํดํ๋ ค๊ณ ๋
ธ๋ ฅํ๊ณ ์์ต๋๋ค. ํ์ฌ ์ ๋ #1158์ด ์๋ ์ด ๋ฌธ์ ์๋ง ์ง์คํ๊ณ ์์ต๋๋ค. ApplicationUp_Uplinkmessage
์์ ์ ์ ์ํ์
จ๋ฏ์ด ์ ๋ ๊ทธ๊ฒ์ ์์๋ด๋ ค๊ณ ๋
ธ๋ ฅํ๊ณ ์์ต๋๋ค. ํ์ฌ ๋ค์๊ณผ ๊ฐ์ ์ง๋ฌธ์ด ์์ต๋๋ค.
1) ApplicationUplink
๊ตฌ์กฐ์ฒด์ ApplicationUp_UplinkMessage
ํจ์๋ ttnpb ๋๋ ํ ๋ฆฌ์ messages.pb.go ํ์ผ์ ์ ์๋์ด ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํ์ผ์ ํค๋์๋ "DO NOT EDIT"๊ฐ ์ธ๊ธ๋์ด ์์ต๋๋ค. ๋ฌด์ํด์ผ ํ๋์? ์๋๋ฉด ๊ทธ๊ฒ์ ์์ ํ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
2) " introduce a new format, based on the JSON one
"์ ๋ํด ์์ธํ ์ค๋ช
ํด ์ฃผ์๊ฒ ์ต๋๊น? ์ ํ์์ ๋ง๋๋ ๋์ ๊ธฐ์กด ํ์์ ์์ ํ๋ฉด ๋๋ค๊ณ ์๊ฐํ์ต๋๋ค.
3) ๋ํ ํ๋์ ๊ฒฐ๊ณผ๋ง ๋ฐํ๋๋ ๊ฒฐ๊ณผ ๋ํ์ ๋ํด์๋ ์ธ๊ธํ์ต๋๋ค. ์ ํํ ๋ฌด์์ ํ ๊ฒ์ธ๊ฐ? ์ฌ๋ฌ ๋ฉ์์ง๋ฅผ ํ๋๋ก ๋ค์ ๊ฒฐํฉํ๊ณ ํ๋์ ๊ฒฐ๊ณผ๋ง ๋ฐํํฉ๋๊น? ๊ทธ๋ฆฌ๊ณ ์
๋งํฌ ๋ฉ์์ง์ ๋ํด์๋ง ๊ทธ๋ ๊ฒ ํด์ผ ํฉ๋๊น?
[์ง์์ ์ธ ์ง๋๋ฅผ ํด์ฃผ์ @adriansmares ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ๋น๋ก golang ํํ ๋ฆฌ์ผ์ ์๊ฐํ์ง๋ง, ์ด๊ฒ์ GO ์ธ์ด์์ ์ฒซ ์ํธ์์ฉ์ ๋๋ค.
*.pb.*
ํ์ผ์ ํธ์งํ ํ์๊ฐ ์์ต๋๋ค. mage proto:all
๋ฅผ ์คํํ ๋ *.proto
ํ์ผ์์ ์๋์ผ๋ก ์์ฑ๋ฉ๋๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ์ด ๋ฌธ์ ์ ๋ชฉ์ ์ ์ํด ๊ทธ๋ฌํ ์์ ์ ์ํํ ํ์๊ฐ ์์ต๋๋ค.์ ์ฒด ํ์ดํ๋ผ์ธ์ ๋ ์ ์ค๋ช ํ๋ ค๊ณ ๋ ธ๋ ฅํ๊ฒ ์ต๋๋ค. ์๋ง๋ ์ด๊ฒ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง์ ๋ํ ๋น์ ๋น์ถฐ์ค ๊ฒ์ ๋๋ค.
*ttnpb.ApplicationUplink
์ ํ์
๋๋ค.FRMPayload
์ ๋ณตํธํ ๊ตฌ์กฐ๋ก ํ๋ DecodedPayload
๋๋ฐ์ด์ค ํ์ด๋ก๋ ํฌ๋งท์ ์ด์ฉํ์ฌ).*ttnpb.ApplicationUp
๋ก ํฌ์ฅํ์ฌ ํ๋ฐํธ์๋(MQTT, ์นํ
, PubSub, ์ ํ๋ฆฌ์ผ์ด์
ํจํค์ง)๋ก ๋ณด๋
๋๋ค.*ttnpb.ApplicationUp
์์ ํ๊ณ ์ค์ (ํ์)์ ๋ฐ๋ผ ์ฌ์ฉํ ํฌ๋งทํฐ๋ฅผ ์ ํํฉ๋๋ค(ํฌ๋งทํฐ ์ธํฐํ์ด์ค๋ pkg/applicationserver/io/formatters
).*ttnph.ApplicationUp
formatter.FromUp
๋ฅผ ํธ์ถํ๊ณ 1 ๋ฉ์์ง์ ๋ณธ๋ฌธ์ ๋ํ๋ด๋ ๋ฐ์ดํธ ์กฐ๊ฐ( []byte
)์ ๋ฐ์ต๋๋ค.์ด์ ์ด ๋ฌธ์ ์ ๊ด๋ จํ์ฌ 6๋จ๊ณ์๋ง ๋ณ๊ฒฝ์ด ํ์ํ๋ค๋ ๊ฒ์ ์ ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
FromUp
๊ฐ ์ฌ๋ฌ ํ์ด๋ก๋(๋ฐ์ดํธ ์กฐ๊ฐ ์กฐ๊ฐ)๋ฅผ ๋ฐํํ ์ ์๋๋ก ์ธํฐํ์ด์ค์ ๊ตฌํ์ ๋ฐํ ์ ํ์ ๋ณ๊ฒฝํฉ๋๋ค.Protobuf
๋ฐ JSON
ํ์์ ๋์์ ๋ณ๊ฒฝํด์๋ ์ ๋๋ฉฐ ๊ณ์ํด์ 1๊ฐ์ ํ์ด๋ก๋๋ง ๋ฐํํด์ผ ํฉ๋๋ค(๊ทธ๋์ ๋ฉ์ด ํ์ํ ์ด์ ).[][]byte
๋ฅผ ๋ฐํํ๋๋ก ์ด 2๊ฐ(์ธํฐํ์ด์ค ๋ฐ ํฌ๋งทํฐ)๋ฅผ ๋ณ๊ฒฝํ๋ฉด ์ค๋ฅ๊ฐ ํ์๋๊ธฐ ์์ํฉ๋๋ค( FromUp
๋ฅผ ํธ์ถํ๋ ๋๋ถ๋ถ์ ์ฅ์์์๋ ํ๋์ ํ์ด๋ก๋๋ง ์์ ํ ๊ฒ์ผ๋ก ์์ํ๋ฏ๋ก ์
๋ฐ์ดํธํด์ผ ํฉ๋๋ค. ์ด๋ฌํ ํธ์ถ ์ฌ์ดํธ๋ ํ์ด๋ก๋ ๋ชฉ๋ก์ ํตํด ๋ฃจํ๋ฅผ ๋ง๋ค๊ณ ๊ฐ๊ฐ์ ๋ณด๋
๋๋ค.๋์์ ์ ํ ๋ณ๊ฒฝํ์ง ์๋ ์ด ๋ฌธ์ ๊ฐ ์์ ๋ ํ์๋ง ๊ฐ ์ธก์ ์ ๋ํด ํ๋์ฉ ์ฌ๋ฌ ํ์ด๋ก๋ ์กฐ๊ฐ์ ๋ฐํํ๋ ๊ณ ์ ํ ํฌ๋งทํฐ๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค(๊ทธ๋ฌ๋ ์ด ์๋ก์ด ํ์์ ์ด ๋ฌธ์ ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ฌ์ต๋๋ค!).
@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 ์
@adriansmares ๋ฌผ๋ก ์ ๋๋ค. ๊ทธ๋ ๊ฒ ํ๊ฒ ์ต๋๋ค. ํด๋น pull ์์ฒญ์ ์ธ๊ธ๋ ํ๊ฒฝ ๋๋ ์ต์ ๋ฒ์ ์ ์คํ์ ๊ธฐ๋ฐ์ผ๋ก ํด์ผ ํฉ๋๊น?
๋์ค์ ์ถฉ๋์ ํผํ๊ธฐ ์ํด ์ต์ master
์์ ๋ณ๊ฒฝ ์ฌํญ์ ๋ค์ ์ ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ด ๋ฌธ์ ๋ ๊ฝค ์ค๋ซ๋์ ๋นํ์ฑํ๋์์ผ๋ฏ๋ก ๋ค์ ๋ถ๋ฅ๋ก ์ด๋ํ์ฌ ์ด์ ๋ํ ์์๊ฐ ์๋์ง ์๋๋ฉด ๊ทธ๋ฅ ์ญ์ ํด์ผ ํ๋์ง ํ์ธํ๊ฒ ์ต๋๋ค.
ํ์ฅ์ฑ์ด ์ข์ง ์๊ธฐ ๋๋ฌธ์ ๋ ์ด์ ํ์ํ์ง ์์ต๋๋ค.