Lorawan-stack: рдПрдХ рдкреНрд░рд╛рд░реВрдк рд╕реЗ рдХрдИ рдкрд░рд┐рдгрд╛рдореА рд╕рдВрджреЗрд╢реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░реЗрдВ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 13 рдЕрдЧре░ 2019  ┬╖  12рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: TheThingsNetwork/lorawan-stack

рд╕рд╛рд░рд╛рдВрд╢

рдПрдХ 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 рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрджрд▓реЗрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рдкреНрд░рддреНрдпреЗрдХ рдлреНрд░рдВрдЯ-рдПрдВрдб рдХреЛ рдХреЗрд╡рд▓ рдПрдХ рдХреЗ рдмрдЬрд╛рдп рд╕рднреА рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдмрджрд▓рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:

рдХреНрдпрд╛ рдЖрдк рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рд╕рдмрдорд┐рдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

рд╣рд╛рдВ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕реЗ рд╕рдореБрджрд╛рдп рдкрд░ рдЫреЛрдбрд╝ рджреВрдВрдЧрд╛ред

application server needtriage

рд╕рднреА 12 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

@adriansmares рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдВред formatter.go рдлрд╝рд╛рдЗрд▓ рдореЗрдВ *ttnpb.ApplicationUp рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП []byte рд╕реЗ [][]byte рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВрдиреЗ рдЗрд╕реЗ json.go рдФрд░ protobuf.go рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рднреА рдмрджрд▓ рджрд┐рдпрд╛ред рд▓реЗрдХрд┐рди рдЕрдм, рдпрд╣ рдирд┐рдореНрди рддреНрд░реБрдЯрд┐ рджреЗрддрд╛ рд╣реИ:
image
рдХреГрдкрдпрд╛ рдХреБрдЫ рд╕реБрдЭрд╛рд╡ рджреЗрдВред рдзрдиреНрдпрд╡рд╛рджред

@ mihirr93 рдЪреВрдВрдХрд┐ рдЕрдм рдЖрдк рдкрд░рд┐рдгрд╛рдореЛрдВ рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рд╕рд╛рдЗрдЯреЛрдВ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ (рдкреНрд░рддреНрдпреЗрдХ рдкрд░рд┐рдгрд╛рдо рдмрд╛рдЗрдЯреНрд╕ рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рд╣реИ), рдЖрдкрдХреЛ рдЙрди рдЬрдЧрд╣реЛрдВ рдХреЛ рд▓рдкреЗрдЯрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд╣рд╛рдВ рдХреЗрд╡рд▓ рдПрдХ рдкрд░рд┐рдгрд╛рдо [][]byte{ slice-containing-result } рд╕рд╛рде рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдирдорд╕реНрдХрд╛рд░ рд╢реНрд░реАрдорд╛рди @adriansmares ред рдореИрдВ рдЕрдкрдиреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рд▓реЗрдХрд░ рдереЛрдбрд╝рд╛ рднреНрд░рдорд┐рдд рд╣реВрдВред рд╣рдо рдлреНрд░рдВрдЯ-рдПрдВрдб рд╕рдВрджреЗрд╢ (рдХрдЪреНрдЪреЗ рдкреЗрд▓реЛрдб) рдХреЛ рдХрдИ рд╕рдВрджреЗрд╢реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЬрд┐рд╕ рдмрд┐рдВрджреБ рдкрд░ рд╕рдВрджреЗрд╢ рдХрд╛рдЯрд╛ рдЬрд╛рдПрдЧрд╛ рд╡рд╣ рдЙрд╕рдХреЗ рдПрдиреНрдХреЛрдбрд┐рдВрдЧ (рдХреИрдпреЗрди рдпрд╛ рдХреЛрдИ рдХрд╕реНрдЯрдо рдПрдиреНрдХреЛрдбрд┐рдВрдЧ) рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЕрдЬреНрдЮрд╛рдд рд╣реИред рддреЛ, рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдбреАрдХреЛрдбреЗрдб рдкреЗрд▓реЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдПрдХ рдмрд╛рд░ рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЯреАрдЯреАрдПрди рдХреЗ рдкреЗрд▓реЛрдб рдкреНрд░рд╛рд░реВрдк рдЯреИрдм рдореЗрдВ рдбрд┐рдХреЛрдбрд░ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ JSON рдореЗрдВ рдбрд┐рдХреЛрдб рдХрд┐рдП рдЧрдП рдорд╛рди рджрд┐рдЦрд╛рддрд╛ рд╣реИ (рдЬреИрд╕рд╛ рдХрд┐ рдЪрд┐рддреНрд░ рдореЗрдВ рджреЗрдЦрд╛ рдЧрдпрд╛ рд╣реИ)ред рдХреНрдпрд╛ рд╣рдореЗрдВ рдЗрд╕ рдбреАрдХреЛрдбреЗрдб рдкреЗрд▓реЛрдб рдХреЛ рд╕реАрдзреЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ http рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдФрд░ рдЖрдЧреЗ рдирд╣реАрдВ рдмрдврд╝рд╛рдирд╛ рдЪрд╛рд╣рд┐рдП?
image
рдХреНрдпрд╛ рдЖрдк рдХреГрдкрдпрд╛ рдЗрд╕ рднреНрд░рдо рдкрд░ рдХреБрдЫ рдкреНрд░рдХрд╛рд╢ рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ?
рдФрд░, рдХреНрдпрд╛ рд╣рдо рд╕рд┐рд░реНрдл pkg рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ .proto рдлрд╛рдЗрд▓реЗрдВ рдЕрдкрдиреЗ рдЖрдк рдЕрдкрдбреЗрдЯ рд╣реЛ рдЬрд╛рдПрдВрдЧреА?
рдЖрдкрдХреА рддрд░рд╣ рдХреЗ рд╕рдорд░реНрдерди рдФрд░ рд╕рдордп рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд-рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рджред

_рдзреНрдпрд╛рди рд░рдЦреЗрдВ рдХрд┐ рдЗрд╕ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рд╣рдорд╛рд░реЗ рд▓реЛрд░рд╛рд╡рди рд╕реНрдЯреИрдХ рдХрд╛ V3 рд╕рдВрд╕реНрдХрд░рдг рд╣реИ, рдФрд░ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдЪрд┐рддреНрд░ TTN рд╕реЗ рд╣реИ, рдЬреЛ V2 рд╕рдВрд╕реНрдХрд░рдг рдЪрд▓рд╛рддрд╛ рд╣реИред_

рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рд░рдЦреЗрдВ рдХрд┐ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдХреЗрд╡рд▓ рдПрдХ рд╕рдВрджреЗрд╢ рд╕реЗ рдХрдИ рдкреЗрд▓реЛрдб рдмрдирд╛рдиреЗ рдХреЗ рд╕рдорд░реНрдерди рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИ, рдФрд░ рдирдП рдкреНрд░рд╛рд░реВрдк рдХрд╛ рдореБрджреНрджрд╛ рдЬрд┐рд╕рдореЗрдВ рдЖрдк рд╢рд╛рдпрдж рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рд╡рд╣ рд╣реИ https://github.com/TheThingsNetwork/lorawan-stack/issues/1158ред рдХреГрдкрдпрд╛ рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╡рд╣реА рд╣реИ рдЬрд┐рд╕реЗ рдЖрдк рдвреВрдВрдв рд░рд╣реЗ рд╣реИрдВред

рдлрд┐рд░ рднреА, рдореИрдВ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕реБрдЭрд╛рд╡ рджреВрдВрдЧрд╛ рдХрд┐ рдЖрдк JSON рд╡рди рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдПрдХ рдирдпрд╛ рдкреНрд░рд╛рд░реВрдк рдкреЗрд╢ рдХрд░реЗрдВ, рдЬреЛ рдЕрдкрд▓рд┐рдВрдХ рдХреЗ рдЕрдВрджрд░ рдорд┐рд▓реА рдбреАрдХреЛрдб рдХреА рдЧрдИ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрдИ рдкреЗрд▓реЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред
рдЖрдк рд╢рд╛рдпрдж ApplicationUp_UplinkMessage рдЕрдкрд▓рд┐рдВрдХ рд╕рдВрджреЗрд╢ рдХреЛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕рдВрднрд╛рд▓рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рд╡реЗ рдлрд╝реАрд▓реНрдб рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЬрд┐рдирдореЗрдВ рдЖрдк DecodedPayload рдлрд╝реАрд▓реНрдб рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВред

рдЗрд╕ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдкреНрд░реЛрдЯреЛ рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред

рдореИрдВ рдЕрднреА рднреА рд╕реНрдЯреИрдХ рдХреЗ рдЖрдВрддрд░рд┐рдХ рдХрд╛рдордХрд╛рдЬ рдФрд░ рдХреЛрдб рдХреЛ рд╕рдордЭрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рд╡рд░реНрддрдорд╛рди рдореЗрдВ, рдореИрдВ рдХреЗрд╡рд▓ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рди рдХрд┐ #1158 рдкрд░ред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдиреЗ ApplicationUp_Uplinkmessage рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ рдерд╛, рдореИрдВ рдЗрд╕рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдЗрд╕ рд╕рдордп рдореЗрд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рд╢реНрди рд╣реИрдВ:
1) рд╕рдВрд░рдЪрдирд╛ ApplicationUplink рдФрд░ func ApplicationUp_UplinkMessage рдХреЛ ttnpb рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд╕рдВрджреЗрд╢реЛрдВ.pb.go рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдлрд╝рд╛рдЗрд▓ рдХреЗ рд╢реАрд░реНрд╖рд▓реЗрдЦ рдореЗрдВ "рд╕рдВрдкрд╛рджрд┐рдд рди рдХрд░реЗрдВ" рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рд╣реИред рдХреНрдпрд╛ рдореБрдЭреЗ рдЗрд╕реЗ рдЕрдирджреЗрдЦрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП? рдпрд╛ рдЗрд╕реЗ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рд╡реИрдХрд▓реНрдкрд┐рдХ рддрд░реАрдХрд╛ рд╣реИ?
2) рдХреНрдпрд╛ рдЖрдк рдХреГрдкрдпрд╛ рдЗрд╕рдХрд╛ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд░реНрдгрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ " introduce a new format, based on the JSON one "? рдореИрдВрдиреЗ рд╕реЛрдЪрд╛ рдХрд┐ рд╣рдореЗрдВ рдирдпрд╛ рдмрдирд╛рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдореМрдЬреВрджрд╛ рдкреНрд░рд╛рд░реВрдк рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
3) рдЖрдкрдиреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рд░реИрдкрд┐рдВрдЧ рдХрд╛ рднреА рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдХреЗрд╡рд▓ рдПрдХ рдкрд░рд┐рдгрд╛рдо рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреНрдпрд╛ рдХрд░реЗрдЧрд╛? рдХреНрдпрд╛ рдпрд╣ рдПрдХрд╛рдзрд┐рдХ рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рдПрдХ рдореЗрдВ рджреЛрдмрд╛рд░рд╛ рдЬреЛрдбрд╝ рджреЗрдЧрд╛ рдФрд░ рдХреЗрд╡рд▓ рдПрдХ рдкрд░рд┐рдгрд╛рдо рд▓реМрдЯрд╛рдПрдЧрд╛? рдФрд░ рдХреНрдпрд╛ рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЕрдкрд▓рд┐рдВрдХ рд╕рдВрджреЗрд╢ рдХреЗ рд▓рд┐рдП рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ?

[рдЖрдкрдХреЗ рдирд┐рд░рдВрддрд░ рдорд╛рд░реНрдЧрджрд░реНрд╢рди рдХреЗ рд▓рд┐рдП @adriansmares рдзрдиреНрдпрд╡рд╛рджред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореИрдВрдиреЗ рдЧреЛрд▓рдВрдЧ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рд▓рд┐рдпрд╛, рдпрд╣ GO рднрд╛рд╖рд╛ рдХреЗ рд╕рд╛рде рдореЗрд░реА рдкрд╣рд▓реА рдмрд╛рддрдЪреАрдд рд╣реИ, рдЖрдкрдХреЛ рдЗрддрдиреЗ рд╕рд╛рд░реЗ рд╕рдВрджреЗрд╣реЛрдВ рд╕реЗ рдкрд░реЗрд╢рд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд╖рдорд╛ рдХрд░реЗрдВ]

  • рдЖрдкрдХреЛ рдЙрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рди рд╣реА рдХрд┐рд╕реА *.pb.* рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛред рдЬрдм рдЖрдк mage proto:all рдЪрд▓рд╛рддреЗ рд╣реИрдВ рддреЛ рдпреЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ *.proto рдлрд╝рд╛рдЗрд▓реЛрдВ рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрддреЗ рд╣реИрдВред рдмрд╣рд░рд╣рд╛рд▓, рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рдкреНрд░рдпреЛрдЬрди рдХреЗ рд▓рд┐рдП рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреЛрдИ рд╕рдВрд╢реЛрдзрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
  • рдХреГрдкрдпрд╛ рджреВрд╕рд░реЗ рдЕрдВрдХ рдореЗрдВ рдЗрд╕рдХрд╛ рдкрд╛рд▓рди рдХрд░реЗрдВред
  • рд░реИрдкрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕реБрдЭрд╛рд╡ рдЖрдкрдХреЛ рдореМрдЬреВрджрд╛ рдХреЛрдб рдХреЛ рдмрд░рдХрд░рд╛рд░ рд░рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ (рдЕрднреА рднреА рдПрдХ рдЕрдкрд▓рд┐рдВрдХ рд╕рдВрджреЗрд╢ рд╕реЗ рдкреЛрд╕реНрдЯ рдХрд┐рдП рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреЗрд▓реЛрдб рд▓реМрдЯрд╛ рд░рд╣рд╛ рд╣реИ)ред

рдореИрдВ рдкреВрд░реА рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЛ рдмреЗрд╣рддрд░ рдврдВрдЧ рд╕реЗ рд╕рдордЭрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реВрдВ, рд╢рд╛рдпрдж рдпрд╣ рдЗрд╕ рдкрд░ рдХреБрдЫ рдкреНрд░рдХрд╛рд╢ рдбрд╛рд▓реЗрдЧрд╛ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ

  1. рдПрдХ рдбрд┐рд╡рд╛рдЗрд╕ 1 рдЕрдкрд▓рд┐рдВрдХ рднреЗрдЬрддрд╛ рд╣реИред
  2. 1 рдЕрдкрд▓рд┐рдВрдХ рдЧреЗрдЯрд╡реЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЧреЗрдЯрд╡реЗ рд╕рд░реНрд╡рд░ рдХреЛ рднреЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдЗрд╕реЗ рдиреЗрдЯрд╡рд░реНрдХ рд╕рд░реНрд╡рд░ рдХреЛ рдЕрдЧреНрд░реЗрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдлрд┐рд░ рдЗрд╕реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рд░реНрд╡рд░ рдХреЛ рдЕрдЧреНрд░реЗрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред AS рддрдХ рдкрд╣реБрдБрдЪрдиреЗ рд╡рд╛рд▓рд╛ рд╕рдВрджреЗрд╢ *ttnpb.ApplicationUplink ред
  3. рдХреЗ рд░реВрдк рдореЗрдВ рдбреАрдХреЛрдб рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рдЕрдкрдиреЗ рджреНрд╡рд┐рдЖрдзрд╛рд░реА рдкреЗрд▓реЛрдб рдХреЛ рдбрд┐рдХреЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ 1 рдЕрдкрд▓рд┐рдВрдХ рдФрд░ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рдкрдбрд╝рддреЗ рд╣реИрдВ (рдореЗрдВ рдмрд╛рдЗрдЯреНрд╕ рдмрд╛рд░реА FRMPayload рдХреЗ рдбреАрдХреЛрдб рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдХреНрд╖реЗрддреНрд░ DecodedPayload ) рдбрд┐рд╡рд╛рдЗрд╕ рдкреЗрд▓реЛрдб рдлрд╝реЙрд░реНрдореЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ред
  4. рдЗрд╕рдХреЗ рдмрд╛рдж рдпрд╣ рдЗрд╕реЗ *ttnpb.ApplicationUp рдореЗрдВ рд▓рдкреЗрдЯрддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдлреНрд░рдВрдЯрдПрдВрдб (рдПрдордХреНрдпреВрдЯреАрдЯреА, рд╡реЗрдмрд╣реБрдХ, рдкрдмрд╕реБрдм, рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкреИрдХреЗрдЬ) рдореЗрдВ рднреЗрдЬрддрд╛ рд╣реИред
  5. рдлрд╝реНрд░рдВрдЯрдПрдВрдб рдХреЛ рдпрд╣ 1 *ttnpb.ApplicationUp рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдЙрдирдХреА рд╕реЗрдЯрд┐рдВрдЧреНрд╕ (рдкреНрд░рд╛рд░реВрдк) рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЪреБрдиреЗрдВ рдХрд┐ рдХрд┐рд╕ рдлрд╝реЙрд░реНрдореЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ (рдлрд╝реЙрд░реНрдореЗрдЯрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ pkg/applicationserver/io/formatters рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ)ред
  6. рдлреНрд░рдВрдЯрдПрдВрдб formatter.FromUp рдХреЛ 1 *ttnph.ApplicationUp formatter.FromUp рд╕рд╛рде рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдмрд╛рдЗрдЯ рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ ( []byte ) рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ, рдЬреЛ 1 рд╕рдВрджреЗрд╢ рдХреЗ рдореБрдЦреНрдп рднрд╛рдЧ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИред

рдЕрдм, рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ, рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдпрд╣ рджрд┐рдЦрд╛рдИ рджреЗ рд░рд╣рд╛ рд╣реИ рдХрд┐ рдХреЗрд╡рд▓ рдЪрд░рдг 6 рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

  • рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рджреЛрдиреЛрдВ рдХреЗ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдмрджрд▓рдирд╛ рдЬреИрд╕реЗ рдХрд┐ FromUp рдПрдХрд╛рдзрд┐рдХ рдкреЗрд▓реЛрдб (рдмрд╛рдЗрдЯ рдХреЗ рд╕реНрд▓рд╛рдЗрд╕ рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛) рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реИред
  • рдореМрдЬреВрджрд╛ Protobuf рдФрд░ JSON рдкреНрд░рд╛рд░реВрдкреЛрдВ рдХреЛ рдЕрдкрдирд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдирд╣реАрдВ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЗрд╕ рддрд░рд╣ рдХреЗрд╡рд▓ 1 рдкреЗрд▓реЛрдб рд▓реМрдЯрд╛рдирд╛ рдЬрд╛рд░реА рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП (рдЗрд╕реАрд▓рд┐рдП рд░реИрдк рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)ред
  • [][]byte рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрди 2 (рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдФрд░ рдлрд╝реЙрд░реНрдореЗрдЯрд░реНрд╕) рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рдж рдЖрдкрдХреЛ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд▓рдЧреЗрдВрдЧреА (рдХреНрдпреЛрдВрдХрд┐ FromUp рдХреЙрд▓ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рдХреЗрд╡рд▓ рдПрдХ рдкреЗрд▓реЛрдб рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рдХреА рдЙрдореНрдореАрдж рд╣реИ - рдЖрдкрдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдЗрди рдХреЙрд▓ рд╕рд╛рдЗрдЯреЛрдВ рдФрд░ рдкреЗрд▓реЛрдб рдХреА рд╕реВрдЪреА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдиреНрд╣реЗрдВ рд▓реВрдк рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рднреЗрдЬрддреЗ рд╣реИрдВред

рдХреЗрд╡рд▓ рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рдмрд╛рдж, рдЬреЛ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИ, рдЖрдк рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдлреЙрд░реНрдореЗрдЯрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рдЖрдЧреЗ рдмрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдХрдИ рдкреЗрд▓реЛрдб рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рд▓реМрдЯрд╛рдПрдЧрд╛, рдкреНрд░рддреНрдпреЗрдХ рдорд╛рдк рдХреЗ рд▓рд┐рдП рдПрдХ (рд▓реЗрдХрд┐рди рдзреНрдпрд╛рди рд░рдЦреЗрдВ рдХрд┐ рдпрд╣ рдирдпрд╛ рдкреНрд░рд╛рд░реВрдк рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИ!)

рдЗрддрдиреА рд╡рд┐рд╕реНрддреГрдд рд╡реНрдпрд╛рдЦреНрдпрд╛ рдФрд░ рдорд╛рд░реНрдЧрджрд░реНрд╢рди рдХреЗ рд▓рд┐рдП ./mage go:test js:test jsSDK:test рд╕рд╛рде рднреА рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдФрд░ рдпрд╣ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред рдХреЛрдб рдореЗрдВ рдХрд┐рдП рдЧрдП рдкреНрд░рдореБрдЦ рдкрд░рд┐рд╡рд░реНрддрди рдиреАрдЪреЗ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд┐рдП рдЧрдП рд╣реИрдВ:
рдлрд╝реЙрд░реНрдореЗрдЯрд░.рдЧреЛ

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
}

рдкреНрд░реЛрдЯреЛрдмрдл.рдЧреЛ
рдКрдкрд░ рдХреА рддрд░рд╣

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
}

рдХреГрдкрдпрд╛ рдЕрдкрдиреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдФрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ рдкреНрд░рджрд╛рди рдХрд░реЗрдВред рдПрдХ рдмрд╛рд░ рдХрд╛рд░реНрдп рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рдиреЗ рдкрд░ рдореИрдВ рдХреЛрдб рд╢реИрд▓реА рджрд┐рд╢рд╛рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕реБрдзрд╛рд░ (рд╡рд░ рдирд╛рдордХрд░рдг, рдЗрдВрдбреЗрдВрдЯреЗрд╢рди, рдЖрджрд┐) рдХрд░реВрдВрдЧрд╛ред рдФрд░ рдЕрдЧрд░ рдпрд╣ рд╕рд╣реА рд▓рдЧрддрд╛ рд╣реИ, рддреЛ рдХреНрдпрд╛ рдЖрдк рдХреГрдкрдпрд╛ рдореБрдЭреЗ #1158 рдЕрдВрдХ рдХреЗ рд▓рд┐рдП рдорд╛рд░реНрдЧрджрд░реНрд╢рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рдЖрдкрдХрд╛ рдзрдиреНрдпрд╡рд╛рджред

@ mihirr93 рдЕрдЪреНрдЫрд╛ рд▓рдЧ рд░рд╣рд╛ рд╣реИ! рдХреГрдкрдпрд╛ рдЕрдкрдиреЗ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░реЗрдВ рдФрд░ рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рд▓рд┐рдП рдкреБрд▓ рдЕрдиреБрд░реЛрдз рд╕рдмрдорд┐рдЯ рдХрд░реЗрдВред рдЗрд╕реЗ рдорд░реНрдЬ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╣рдо #1158 рдореЗрдВ рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рдирдП рдлреЙрд░реНрдореЗрдЯрд░ рдХреА рдУрд░ рдЖрдЧреЗ рдмрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред

@adriansmares рдЬрд╝рд░реВрд░, рдореИрдВ рд╡рд╣ рдХрд░реВрдБрдЧрд╛ред рдХреНрдпрд╛ рд╡рд╣ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рд╡рд╛рддрд╛рд╡рд░рдг рдпрд╛ рд╕реНрдЯреИрдХ рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП?

рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ рдХрд┐ рдЖрдк рдмрд╛рдж рдореЗрдВ рд╡рд┐рд░реЛрдз рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдирд╡реАрдирддрдо master рдКрдкрд░ рд░реАрдмреЗрд╕ рдХрд░реЗрдВред

рдпрд╣ рдореБрджреНрджрд╛ рдХрд╛рдлреА рд╕рдордп рд╕реЗ рдирд┐рд╖реНрдХреНрд░рд┐рдп рд╣реИ, рддреЛ рдЪрд▓рд┐рдП рдЗрд╕реЗ рд╡рд╛рдкрд╕ рдЯреНрд░рд╛рдЗрдПрдЬ рдореЗрдВ рд▓реЗ рдЬрд╛рддреЗ рд╣реИрдВ рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХреНрдпрд╛ рдЕрднреА рднреА рдЗрд╕рдХреА рдорд╛рдВрдЧ рд╣реИ, рдпрд╛ рд╣рдореЗрдВ рдЗрд╕реЗ рдЫреЛрдбрд╝ рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЗрд╕рдХреА рдЕрдм рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЦрд░рд╛рдм рдкреИрдорд╛рдиреЗ рдкрд░ рд╣реИред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

thinkOfaNumber picture thinkOfaNumber  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

bafonins picture bafonins  ┬╖  5рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

johanstokking picture johanstokking  ┬╖  8рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

MatteMoveSRL picture MatteMoveSRL  ┬╖  7рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

adamsondelacruz picture adamsondelacruz  ┬╖  7рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ