diff --git a/translated_images/IMG_5305.aa291c8812a9f1e5b08f3e789f9858e9eacc88c4bbc23296df1bffbbd9c671b3.es.png b/translated_images/IMG_5305.aa291c8812a9f1e5b08f3e789f9858e9eacc88c4bbc23296df1bffbbd9c671b3.es.png new file mode 100644 index 00000000..1ba4f5c7 Binary files /dev/null and b/translated_images/IMG_5305.aa291c8812a9f1e5b08f3e789f9858e9eacc88c4bbc23296df1bffbbd9c671b3.es.png differ diff --git a/translated_images/IMG_5305.aa291c8812a9f1e5b08f3e789f9858e9eacc88c4bbc23296df1bffbbd9c671b3.hk.png b/translated_images/IMG_5305.aa291c8812a9f1e5b08f3e789f9858e9eacc88c4bbc23296df1bffbbd9c671b3.hk.png new file mode 100644 index 00000000..1ba4f5c7 Binary files /dev/null and b/translated_images/IMG_5305.aa291c8812a9f1e5b08f3e789f9858e9eacc88c4bbc23296df1bffbbd9c671b3.hk.png differ diff --git a/translated_images/IMG_5306.d575b9ab7025877b0ceba872490fa561edf3c4fcd5e8cca4ae2607a309d48c50.es.png b/translated_images/IMG_5306.d575b9ab7025877b0ceba872490fa561edf3c4fcd5e8cca4ae2607a309d48c50.es.png new file mode 100644 index 00000000..3cac91bb Binary files /dev/null and b/translated_images/IMG_5306.d575b9ab7025877b0ceba872490fa561edf3c4fcd5e8cca4ae2607a309d48c50.es.png differ diff --git a/translated_images/IMG_5306.d575b9ab7025877b0ceba872490fa561edf3c4fcd5e8cca4ae2607a309d48c50.hk.png b/translated_images/IMG_5306.d575b9ab7025877b0ceba872490fa561edf3c4fcd5e8cca4ae2607a309d48c50.hk.png new file mode 100644 index 00000000..3cac91bb Binary files /dev/null and b/translated_images/IMG_5306.d575b9ab7025877b0ceba872490fa561edf3c4fcd5e8cca4ae2607a309d48c50.hk.png differ diff --git a/translated_images/IMG_5307.f9c9b8361a8aa7345cc6e8ae05cf6b7583d43d3c37ecfbd76d3fdc531e3ac59c.es.png b/translated_images/IMG_5307.f9c9b8361a8aa7345cc6e8ae05cf6b7583d43d3c37ecfbd76d3fdc531e3ac59c.es.png new file mode 100644 index 00000000..967e6539 Binary files /dev/null and b/translated_images/IMG_5307.f9c9b8361a8aa7345cc6e8ae05cf6b7583d43d3c37ecfbd76d3fdc531e3ac59c.es.png differ diff --git a/translated_images/IMG_5307.f9c9b8361a8aa7345cc6e8ae05cf6b7583d43d3c37ecfbd76d3fdc531e3ac59c.hk.png b/translated_images/IMG_5307.f9c9b8361a8aa7345cc6e8ae05cf6b7583d43d3c37ecfbd76d3fdc531e3ac59c.hk.png new file mode 100644 index 00000000..967e6539 Binary files /dev/null and b/translated_images/IMG_5307.f9c9b8361a8aa7345cc6e8ae05cf6b7583d43d3c37ecfbd76d3fdc531e3ac59c.hk.png differ diff --git a/translated_images/IMG_5308.cbd6ed7007e6906012162c19b9e4097936c57873cdb2e54159899066c4281dc5.es.png b/translated_images/IMG_5308.cbd6ed7007e6906012162c19b9e4097936c57873cdb2e54159899066c4281dc5.es.png new file mode 100644 index 00000000..247c1dd6 Binary files /dev/null and b/translated_images/IMG_5308.cbd6ed7007e6906012162c19b9e4097936c57873cdb2e54159899066c4281dc5.es.png differ diff --git a/translated_images/IMG_5308.cbd6ed7007e6906012162c19b9e4097936c57873cdb2e54159899066c4281dc5.hk.png b/translated_images/IMG_5308.cbd6ed7007e6906012162c19b9e4097936c57873cdb2e54159899066c4281dc5.hk.png new file mode 100644 index 00000000..247c1dd6 Binary files /dev/null and b/translated_images/IMG_5308.cbd6ed7007e6906012162c19b9e4097936c57873cdb2e54159899066c4281dc5.hk.png differ diff --git a/translated_images/IMG_5309.23fbc3b6667bfb64fa44804f835f38885ad37d02b0a1c1c6e8d89f9a78ba19b4.es.png b/translated_images/IMG_5309.23fbc3b6667bfb64fa44804f835f38885ad37d02b0a1c1c6e8d89f9a78ba19b4.es.png new file mode 100644 index 00000000..e89d81c4 Binary files /dev/null and b/translated_images/IMG_5309.23fbc3b6667bfb64fa44804f835f38885ad37d02b0a1c1c6e8d89f9a78ba19b4.es.png differ diff --git a/translated_images/IMG_5309.23fbc3b6667bfb64fa44804f835f38885ad37d02b0a1c1c6e8d89f9a78ba19b4.hk.png b/translated_images/IMG_5309.23fbc3b6667bfb64fa44804f835f38885ad37d02b0a1c1c6e8d89f9a78ba19b4.hk.png new file mode 100644 index 00000000..e89d81c4 Binary files /dev/null and b/translated_images/IMG_5309.23fbc3b6667bfb64fa44804f835f38885ad37d02b0a1c1c6e8d89f9a78ba19b4.hk.png differ diff --git a/translated_images/IMG_5310.0ee0eb2fbc1c2d0e2d331e74d32b371a4086c07b0839817e9d6b7d4b5c98fc60.es.png b/translated_images/IMG_5310.0ee0eb2fbc1c2d0e2d331e74d32b371a4086c07b0839817e9d6b7d4b5c98fc60.es.png new file mode 100644 index 00000000..0237836d Binary files /dev/null and b/translated_images/IMG_5310.0ee0eb2fbc1c2d0e2d331e74d32b371a4086c07b0839817e9d6b7d4b5c98fc60.es.png differ diff --git a/translated_images/IMG_5310.0ee0eb2fbc1c2d0e2d331e74d32b371a4086c07b0839817e9d6b7d4b5c98fc60.hk.png b/translated_images/IMG_5310.0ee0eb2fbc1c2d0e2d331e74d32b371a4086c07b0839817e9d6b7d4b5c98fc60.hk.png new file mode 100644 index 00000000..0237836d Binary files /dev/null and b/translated_images/IMG_5310.0ee0eb2fbc1c2d0e2d331e74d32b371a4086c07b0839817e9d6b7d4b5c98fc60.hk.png differ diff --git a/translated_images/IMG_5311.8c90da6446c2d8c2ad70dd9e64f29b2b6f2b4d117f8502c3181be66297cc84da.es.png b/translated_images/IMG_5311.8c90da6446c2d8c2ad70dd9e64f29b2b6f2b4d117f8502c3181be66297cc84da.es.png new file mode 100644 index 00000000..4229fee0 Binary files /dev/null and b/translated_images/IMG_5311.8c90da6446c2d8c2ad70dd9e64f29b2b6f2b4d117f8502c3181be66297cc84da.es.png differ diff --git a/translated_images/IMG_5311.8c90da6446c2d8c2ad70dd9e64f29b2b6f2b4d117f8502c3181be66297cc84da.hk.png b/translated_images/IMG_5311.8c90da6446c2d8c2ad70dd9e64f29b2b6f2b4d117f8502c3181be66297cc84da.hk.png new file mode 100644 index 00000000..4229fee0 Binary files /dev/null and b/translated_images/IMG_5311.8c90da6446c2d8c2ad70dd9e64f29b2b6f2b4d117f8502c3181be66297cc84da.hk.png differ diff --git a/translated_images/IMG_5312.a45550ddd8ce8e654919361d52b919e2f8b1dbd01439268b5d3b813133a4e19b.es.png b/translated_images/IMG_5312.a45550ddd8ce8e654919361d52b919e2f8b1dbd01439268b5d3b813133a4e19b.es.png new file mode 100644 index 00000000..9b503ac8 Binary files /dev/null and b/translated_images/IMG_5312.a45550ddd8ce8e654919361d52b919e2f8b1dbd01439268b5d3b813133a4e19b.es.png differ diff --git a/translated_images/IMG_5312.a45550ddd8ce8e654919361d52b919e2f8b1dbd01439268b5d3b813133a4e19b.hk.png b/translated_images/IMG_5312.a45550ddd8ce8e654919361d52b919e2f8b1dbd01439268b5d3b813133a4e19b.hk.png new file mode 100644 index 00000000..9b503ac8 Binary files /dev/null and b/translated_images/IMG_5312.a45550ddd8ce8e654919361d52b919e2f8b1dbd01439268b5d3b813133a4e19b.hk.png differ diff --git a/translated_images/IMG_5313.ed1b45211271dbd23dc596ce9f72078aba665bd5f21088a616a85dd966100427.es.png b/translated_images/IMG_5313.ed1b45211271dbd23dc596ce9f72078aba665bd5f21088a616a85dd966100427.es.png new file mode 100644 index 00000000..c98b7aaf Binary files /dev/null and b/translated_images/IMG_5313.ed1b45211271dbd23dc596ce9f72078aba665bd5f21088a616a85dd966100427.es.png differ diff --git a/translated_images/IMG_5313.ed1b45211271dbd23dc596ce9f72078aba665bd5f21088a616a85dd966100427.hk.png b/translated_images/IMG_5313.ed1b45211271dbd23dc596ce9f72078aba665bd5f21088a616a85dd966100427.hk.png new file mode 100644 index 00000000..c98b7aaf Binary files /dev/null and b/translated_images/IMG_5313.ed1b45211271dbd23dc596ce9f72078aba665bd5f21088a616a85dd966100427.hk.png differ diff --git a/translated_images/IMG_5314.c2203206a05a74b5a4f10a68bbe274e65849a63e1fefe008b2c94be4ae86839c.es.png b/translated_images/IMG_5314.c2203206a05a74b5a4f10a68bbe274e65849a63e1fefe008b2c94be4ae86839c.es.png new file mode 100644 index 00000000..706f83bc Binary files /dev/null and b/translated_images/IMG_5314.c2203206a05a74b5a4f10a68bbe274e65849a63e1fefe008b2c94be4ae86839c.es.png differ diff --git a/translated_images/IMG_5314.c2203206a05a74b5a4f10a68bbe274e65849a63e1fefe008b2c94be4ae86839c.hk.png b/translated_images/IMG_5314.c2203206a05a74b5a4f10a68bbe274e65849a63e1fefe008b2c94be4ae86839c.hk.png new file mode 100644 index 00000000..706f83bc Binary files /dev/null and b/translated_images/IMG_5314.c2203206a05a74b5a4f10a68bbe274e65849a63e1fefe008b2c94be4ae86839c.hk.png differ diff --git a/translated_images/IMG_5315.f698228e0e031bd430efcfab0d08b00d9f3af5289133ce88a9f56c0c3478cd71.es.png b/translated_images/IMG_5315.f698228e0e031bd430efcfab0d08b00d9f3af5289133ce88a9f56c0c3478cd71.es.png new file mode 100644 index 00000000..76bec4da Binary files /dev/null and b/translated_images/IMG_5315.f698228e0e031bd430efcfab0d08b00d9f3af5289133ce88a9f56c0c3478cd71.es.png differ diff --git a/translated_images/IMG_5315.f698228e0e031bd430efcfab0d08b00d9f3af5289133ce88a9f56c0c3478cd71.hk.png b/translated_images/IMG_5315.f698228e0e031bd430efcfab0d08b00d9f3af5289133ce88a9f56c0c3478cd71.hk.png new file mode 100644 index 00000000..76bec4da Binary files /dev/null and b/translated_images/IMG_5315.f698228e0e031bd430efcfab0d08b00d9f3af5289133ce88a9f56c0c3478cd71.hk.png differ diff --git a/translated_images/IMG_5316.29dc70d802ce83497258426614e3e1426a91d6f9777e853daa4a9351b841b94f.es.png b/translated_images/IMG_5316.29dc70d802ce83497258426614e3e1426a91d6f9777e853daa4a9351b841b94f.es.png new file mode 100644 index 00000000..b49060a2 Binary files /dev/null and b/translated_images/IMG_5316.29dc70d802ce83497258426614e3e1426a91d6f9777e853daa4a9351b841b94f.es.png differ diff --git a/translated_images/IMG_5316.29dc70d802ce83497258426614e3e1426a91d6f9777e853daa4a9351b841b94f.hk.png b/translated_images/IMG_5316.29dc70d802ce83497258426614e3e1426a91d6f9777e853daa4a9351b841b94f.hk.png new file mode 100644 index 00000000..b49060a2 Binary files /dev/null and b/translated_images/IMG_5316.29dc70d802ce83497258426614e3e1426a91d6f9777e853daa4a9351b841b94f.hk.png differ diff --git a/translated_images/IMG_5317.ed81e4c1ca5046dc50613049e39c905157fbb318ea19db44c738db513ac501b1.es.png b/translated_images/IMG_5317.ed81e4c1ca5046dc50613049e39c905157fbb318ea19db44c738db513ac501b1.es.png new file mode 100644 index 00000000..3ca064d5 Binary files /dev/null and b/translated_images/IMG_5317.ed81e4c1ca5046dc50613049e39c905157fbb318ea19db44c738db513ac501b1.es.png differ diff --git a/translated_images/IMG_5317.ed81e4c1ca5046dc50613049e39c905157fbb318ea19db44c738db513ac501b1.hk.png b/translated_images/IMG_5317.ed81e4c1ca5046dc50613049e39c905157fbb318ea19db44c738db513ac501b1.hk.png new file mode 100644 index 00000000..3ca064d5 Binary files /dev/null and b/translated_images/IMG_5317.ed81e4c1ca5046dc50613049e39c905157fbb318ea19db44c738db513ac501b1.hk.png differ diff --git a/translated_images/IMG_5318.15dfffeb7f47abf7ca0393628024c1fd45761193ab23185c315e899bd0e7048b.es.png b/translated_images/IMG_5318.15dfffeb7f47abf7ca0393628024c1fd45761193ab23185c315e899bd0e7048b.es.png new file mode 100644 index 00000000..1f5f2412 Binary files /dev/null and b/translated_images/IMG_5318.15dfffeb7f47abf7ca0393628024c1fd45761193ab23185c315e899bd0e7048b.es.png differ diff --git a/translated_images/IMG_5318.15dfffeb7f47abf7ca0393628024c1fd45761193ab23185c315e899bd0e7048b.hk.png b/translated_images/IMG_5318.15dfffeb7f47abf7ca0393628024c1fd45761193ab23185c315e899bd0e7048b.hk.png new file mode 100644 index 00000000..1f5f2412 Binary files /dev/null and b/translated_images/IMG_5318.15dfffeb7f47abf7ca0393628024c1fd45761193ab23185c315e899bd0e7048b.hk.png differ diff --git a/translated_images/IMG_5319.b549b1fff0dcf143c2483044d0519a3c6dc3de12c88860911b378688e7a4e01b.es.png b/translated_images/IMG_5319.b549b1fff0dcf143c2483044d0519a3c6dc3de12c88860911b378688e7a4e01b.es.png new file mode 100644 index 00000000..2953cea1 Binary files /dev/null and b/translated_images/IMG_5319.b549b1fff0dcf143c2483044d0519a3c6dc3de12c88860911b378688e7a4e01b.es.png differ diff --git a/translated_images/IMG_5319.b549b1fff0dcf143c2483044d0519a3c6dc3de12c88860911b378688e7a4e01b.hk.png b/translated_images/IMG_5319.b549b1fff0dcf143c2483044d0519a3c6dc3de12c88860911b378688e7a4e01b.hk.png new file mode 100644 index 00000000..2953cea1 Binary files /dev/null and b/translated_images/IMG_5319.b549b1fff0dcf143c2483044d0519a3c6dc3de12c88860911b378688e7a4e01b.hk.png differ diff --git a/translated_images/IMG_5320.8268d3f61972f348df46401d107399af17512db9ef769f6a44c6cbb18faba998.es.png b/translated_images/IMG_5320.8268d3f61972f348df46401d107399af17512db9ef769f6a44c6cbb18faba998.es.png new file mode 100644 index 00000000..2ce7dedf Binary files /dev/null and b/translated_images/IMG_5320.8268d3f61972f348df46401d107399af17512db9ef769f6a44c6cbb18faba998.es.png differ diff --git a/translated_images/IMG_5320.8268d3f61972f348df46401d107399af17512db9ef769f6a44c6cbb18faba998.hk.png b/translated_images/IMG_5320.8268d3f61972f348df46401d107399af17512db9ef769f6a44c6cbb18faba998.hk.png new file mode 100644 index 00000000..2ce7dedf Binary files /dev/null and b/translated_images/IMG_5320.8268d3f61972f348df46401d107399af17512db9ef769f6a44c6cbb18faba998.hk.png differ diff --git a/translated_images/IMG_5321.b207cf143a59458d150cb1fbd44c3678d14f9cfffe77a0ec64e1cdfe1436df1c.es.png b/translated_images/IMG_5321.b207cf143a59458d150cb1fbd44c3678d14f9cfffe77a0ec64e1cdfe1436df1c.es.png new file mode 100644 index 00000000..157c08c6 Binary files /dev/null and b/translated_images/IMG_5321.b207cf143a59458d150cb1fbd44c3678d14f9cfffe77a0ec64e1cdfe1436df1c.es.png differ diff --git a/translated_images/IMG_5321.b207cf143a59458d150cb1fbd44c3678d14f9cfffe77a0ec64e1cdfe1436df1c.hk.png b/translated_images/IMG_5321.b207cf143a59458d150cb1fbd44c3678d14f9cfffe77a0ec64e1cdfe1436df1c.hk.png new file mode 100644 index 00000000..157c08c6 Binary files /dev/null and b/translated_images/IMG_5321.b207cf143a59458d150cb1fbd44c3678d14f9cfffe77a0ec64e1cdfe1436df1c.hk.png differ diff --git a/translated_images/IMG_5322.974809b9461a9e200e99ae46142b4885e093e5b9b668e0fd818de461e27856a7.es.png b/translated_images/IMG_5322.974809b9461a9e200e99ae46142b4885e093e5b9b668e0fd818de461e27856a7.es.png new file mode 100644 index 00000000..031361a6 Binary files /dev/null and b/translated_images/IMG_5322.974809b9461a9e200e99ae46142b4885e093e5b9b668e0fd818de461e27856a7.es.png differ diff --git a/translated_images/IMG_5322.974809b9461a9e200e99ae46142b4885e093e5b9b668e0fd818de461e27856a7.hk.png b/translated_images/IMG_5322.974809b9461a9e200e99ae46142b4885e093e5b9b668e0fd818de461e27856a7.hk.png new file mode 100644 index 00000000..031361a6 Binary files /dev/null and b/translated_images/IMG_5322.974809b9461a9e200e99ae46142b4885e093e5b9b668e0fd818de461e27856a7.hk.png differ diff --git a/translated_images/IMG_5323.4939fa17958f291bb856032bbd044a709c0199b2e3846f1801a7836d4455dd26.es.png b/translated_images/IMG_5323.4939fa17958f291bb856032bbd044a709c0199b2e3846f1801a7836d4455dd26.es.png new file mode 100644 index 00000000..3a43eb23 Binary files /dev/null and b/translated_images/IMG_5323.4939fa17958f291bb856032bbd044a709c0199b2e3846f1801a7836d4455dd26.es.png differ diff --git a/translated_images/IMG_5323.4939fa17958f291bb856032bbd044a709c0199b2e3846f1801a7836d4455dd26.hk.png b/translated_images/IMG_5323.4939fa17958f291bb856032bbd044a709c0199b2e3846f1801a7836d4455dd26.hk.png new file mode 100644 index 00000000..3a43eb23 Binary files /dev/null and b/translated_images/IMG_5323.4939fa17958f291bb856032bbd044a709c0199b2e3846f1801a7836d4455dd26.hk.png differ diff --git a/translated_images/IMG_5324.0afbc6f0caceb1a341a9606fc9b879938eebebbc8401fce37dff2b167ed4b410.es.png b/translated_images/IMG_5324.0afbc6f0caceb1a341a9606fc9b879938eebebbc8401fce37dff2b167ed4b410.es.png new file mode 100644 index 00000000..7c9552e3 Binary files /dev/null and b/translated_images/IMG_5324.0afbc6f0caceb1a341a9606fc9b879938eebebbc8401fce37dff2b167ed4b410.es.png differ diff --git a/translated_images/IMG_5324.0afbc6f0caceb1a341a9606fc9b879938eebebbc8401fce37dff2b167ed4b410.hk.png b/translated_images/IMG_5324.0afbc6f0caceb1a341a9606fc9b879938eebebbc8401fce37dff2b167ed4b410.hk.png new file mode 100644 index 00000000..7c9552e3 Binary files /dev/null and b/translated_images/IMG_5324.0afbc6f0caceb1a341a9606fc9b879938eebebbc8401fce37dff2b167ed4b410.hk.png differ diff --git a/translated_images/IMG_5325.9e9d9e9b85a10b06ac6038bf88ef91ef56fd371ed9e67b53495cd6878019faf9.es.png b/translated_images/IMG_5325.9e9d9e9b85a10b06ac6038bf88ef91ef56fd371ed9e67b53495cd6878019faf9.es.png new file mode 100644 index 00000000..78f695b7 Binary files /dev/null and b/translated_images/IMG_5325.9e9d9e9b85a10b06ac6038bf88ef91ef56fd371ed9e67b53495cd6878019faf9.es.png differ diff --git a/translated_images/IMG_5325.9e9d9e9b85a10b06ac6038bf88ef91ef56fd371ed9e67b53495cd6878019faf9.hk.png b/translated_images/IMG_5325.9e9d9e9b85a10b06ac6038bf88ef91ef56fd371ed9e67b53495cd6878019faf9.hk.png new file mode 100644 index 00000000..78f695b7 Binary files /dev/null and b/translated_images/IMG_5325.9e9d9e9b85a10b06ac6038bf88ef91ef56fd371ed9e67b53495cd6878019faf9.hk.png differ diff --git a/translated_images/IMG_5326.35bbc9e054c704d0418a8ba7418aa38f51baee13bd2b00cfe8300e1500fa9f32.es.png b/translated_images/IMG_5326.35bbc9e054c704d0418a8ba7418aa38f51baee13bd2b00cfe8300e1500fa9f32.es.png new file mode 100644 index 00000000..77f563fb Binary files /dev/null and b/translated_images/IMG_5326.35bbc9e054c704d0418a8ba7418aa38f51baee13bd2b00cfe8300e1500fa9f32.es.png differ diff --git a/translated_images/IMG_5326.35bbc9e054c704d0418a8ba7418aa38f51baee13bd2b00cfe8300e1500fa9f32.hk.png b/translated_images/IMG_5326.35bbc9e054c704d0418a8ba7418aa38f51baee13bd2b00cfe8300e1500fa9f32.hk.png new file mode 100644 index 00000000..77f563fb Binary files /dev/null and b/translated_images/IMG_5326.35bbc9e054c704d0418a8ba7418aa38f51baee13bd2b00cfe8300e1500fa9f32.hk.png differ diff --git a/translated_images/IMG_5327.804b63a605b5a77a7b60c2fbf370be0f7364f2b5acb98c736420728e61845b62.es.png b/translated_images/IMG_5327.804b63a605b5a77a7b60c2fbf370be0f7364f2b5acb98c736420728e61845b62.es.png new file mode 100644 index 00000000..8dccd514 Binary files /dev/null and b/translated_images/IMG_5327.804b63a605b5a77a7b60c2fbf370be0f7364f2b5acb98c736420728e61845b62.es.png differ diff --git a/translated_images/IMG_5327.804b63a605b5a77a7b60c2fbf370be0f7364f2b5acb98c736420728e61845b62.hk.png b/translated_images/IMG_5327.804b63a605b5a77a7b60c2fbf370be0f7364f2b5acb98c736420728e61845b62.hk.png new file mode 100644 index 00000000..8dccd514 Binary files /dev/null and b/translated_images/IMG_5327.804b63a605b5a77a7b60c2fbf370be0f7364f2b5acb98c736420728e61845b62.hk.png differ diff --git a/translated_images/IMG_5328.925a9da23d96759f6c7c13bfcd94b8063bb5082d2e8a0431058c057e6d14446b.es.png b/translated_images/IMG_5328.925a9da23d96759f6c7c13bfcd94b8063bb5082d2e8a0431058c057e6d14446b.es.png new file mode 100644 index 00000000..b75e015e Binary files /dev/null and b/translated_images/IMG_5328.925a9da23d96759f6c7c13bfcd94b8063bb5082d2e8a0431058c057e6d14446b.es.png differ diff --git a/translated_images/IMG_5328.925a9da23d96759f6c7c13bfcd94b8063bb5082d2e8a0431058c057e6d14446b.hk.png b/translated_images/IMG_5328.925a9da23d96759f6c7c13bfcd94b8063bb5082d2e8a0431058c057e6d14446b.hk.png new file mode 100644 index 00000000..b75e015e Binary files /dev/null and b/translated_images/IMG_5328.925a9da23d96759f6c7c13bfcd94b8063bb5082d2e8a0431058c057e6d14446b.hk.png differ diff --git a/translated_images/IMG_5329.27da5fcbc3336773e94bbd2640df07799c76051bf97d2db7891d47bc462c6e09.es.png b/translated_images/IMG_5329.27da5fcbc3336773e94bbd2640df07799c76051bf97d2db7891d47bc462c6e09.es.png new file mode 100644 index 00000000..5bfed282 Binary files /dev/null and b/translated_images/IMG_5329.27da5fcbc3336773e94bbd2640df07799c76051bf97d2db7891d47bc462c6e09.es.png differ diff --git a/translated_images/IMG_5329.27da5fcbc3336773e94bbd2640df07799c76051bf97d2db7891d47bc462c6e09.hk.png b/translated_images/IMG_5329.27da5fcbc3336773e94bbd2640df07799c76051bf97d2db7891d47bc462c6e09.hk.png new file mode 100644 index 00000000..5bfed282 Binary files /dev/null and b/translated_images/IMG_5329.27da5fcbc3336773e94bbd2640df07799c76051bf97d2db7891d47bc462c6e09.hk.png differ diff --git a/translated_images/IMG_5330.3db3d5ea01c8cca2ae41cf5ea501a0a836569a3abbc2ae95696e0ad1dd005b6a.es.png b/translated_images/IMG_5330.3db3d5ea01c8cca2ae41cf5ea501a0a836569a3abbc2ae95696e0ad1dd005b6a.es.png new file mode 100644 index 00000000..34ca765c Binary files /dev/null and b/translated_images/IMG_5330.3db3d5ea01c8cca2ae41cf5ea501a0a836569a3abbc2ae95696e0ad1dd005b6a.es.png differ diff --git a/translated_images/IMG_5330.3db3d5ea01c8cca2ae41cf5ea501a0a836569a3abbc2ae95696e0ad1dd005b6a.hk.png b/translated_images/IMG_5330.3db3d5ea01c8cca2ae41cf5ea501a0a836569a3abbc2ae95696e0ad1dd005b6a.hk.png new file mode 100644 index 00000000..34ca765c Binary files /dev/null and b/translated_images/IMG_5330.3db3d5ea01c8cca2ae41cf5ea501a0a836569a3abbc2ae95696e0ad1dd005b6a.hk.png differ diff --git a/translated_images/IMG_5331.181987d3d094472fbf569a61760fadf282575f2821138de50007e408fd63182e.es.png b/translated_images/IMG_5331.181987d3d094472fbf569a61760fadf282575f2821138de50007e408fd63182e.es.png new file mode 100644 index 00000000..d1f7bc09 Binary files /dev/null and b/translated_images/IMG_5331.181987d3d094472fbf569a61760fadf282575f2821138de50007e408fd63182e.es.png differ diff --git a/translated_images/IMG_5331.181987d3d094472fbf569a61760fadf282575f2821138de50007e408fd63182e.hk.png b/translated_images/IMG_5331.181987d3d094472fbf569a61760fadf282575f2821138de50007e408fd63182e.hk.png new file mode 100644 index 00000000..d1f7bc09 Binary files /dev/null and b/translated_images/IMG_5331.181987d3d094472fbf569a61760fadf282575f2821138de50007e408fd63182e.hk.png differ diff --git a/translated_images/IMG_5332.4beed56eaa5158e3785dbacb53c9670a0ef1699ce386528f4bb9bad50adf88ca.es.png b/translated_images/IMG_5332.4beed56eaa5158e3785dbacb53c9670a0ef1699ce386528f4bb9bad50adf88ca.es.png new file mode 100644 index 00000000..c215b446 Binary files /dev/null and b/translated_images/IMG_5332.4beed56eaa5158e3785dbacb53c9670a0ef1699ce386528f4bb9bad50adf88ca.es.png differ diff --git a/translated_images/IMG_5332.4beed56eaa5158e3785dbacb53c9670a0ef1699ce386528f4bb9bad50adf88ca.hk.png b/translated_images/IMG_5332.4beed56eaa5158e3785dbacb53c9670a0ef1699ce386528f4bb9bad50adf88ca.hk.png new file mode 100644 index 00000000..c215b446 Binary files /dev/null and b/translated_images/IMG_5332.4beed56eaa5158e3785dbacb53c9670a0ef1699ce386528f4bb9bad50adf88ca.hk.png differ diff --git a/translated_images/IMG_5333.53c3364c2ee0e7bb5db0e299915faaf31e47bb99ad045ec8f6de6ca23d323f47.es.png b/translated_images/IMG_5333.53c3364c2ee0e7bb5db0e299915faaf31e47bb99ad045ec8f6de6ca23d323f47.es.png new file mode 100644 index 00000000..63f58daa Binary files /dev/null and b/translated_images/IMG_5333.53c3364c2ee0e7bb5db0e299915faaf31e47bb99ad045ec8f6de6ca23d323f47.es.png differ diff --git a/translated_images/IMG_5333.53c3364c2ee0e7bb5db0e299915faaf31e47bb99ad045ec8f6de6ca23d323f47.hk.png b/translated_images/IMG_5333.53c3364c2ee0e7bb5db0e299915faaf31e47bb99ad045ec8f6de6ca23d323f47.hk.png new file mode 100644 index 00000000..63f58daa Binary files /dev/null and b/translated_images/IMG_5333.53c3364c2ee0e7bb5db0e299915faaf31e47bb99ad045ec8f6de6ca23d323f47.hk.png differ diff --git a/translated_images/IMG_5334.979472e433948c109b122ae4bbd0f96971dc2e7b1e64615776ebb7337a97e183.es.png b/translated_images/IMG_5334.979472e433948c109b122ae4bbd0f96971dc2e7b1e64615776ebb7337a97e183.es.png new file mode 100644 index 00000000..3eb38501 Binary files /dev/null and b/translated_images/IMG_5334.979472e433948c109b122ae4bbd0f96971dc2e7b1e64615776ebb7337a97e183.es.png differ diff --git a/translated_images/IMG_5334.979472e433948c109b122ae4bbd0f96971dc2e7b1e64615776ebb7337a97e183.hk.png b/translated_images/IMG_5334.979472e433948c109b122ae4bbd0f96971dc2e7b1e64615776ebb7337a97e183.hk.png new file mode 100644 index 00000000..3eb38501 Binary files /dev/null and b/translated_images/IMG_5334.979472e433948c109b122ae4bbd0f96971dc2e7b1e64615776ebb7337a97e183.hk.png differ diff --git a/translated_images/IMG_5335.9f5bfba69a8d5a901c3e3b994a69f62a00d73ef9209b85561553d2ae99a56615.es.png b/translated_images/IMG_5335.9f5bfba69a8d5a901c3e3b994a69f62a00d73ef9209b85561553d2ae99a56615.es.png new file mode 100644 index 00000000..4f960870 Binary files /dev/null and b/translated_images/IMG_5335.9f5bfba69a8d5a901c3e3b994a69f62a00d73ef9209b85561553d2ae99a56615.es.png differ diff --git a/translated_images/IMG_5335.9f5bfba69a8d5a901c3e3b994a69f62a00d73ef9209b85561553d2ae99a56615.hk.png b/translated_images/IMG_5335.9f5bfba69a8d5a901c3e3b994a69f62a00d73ef9209b85561553d2ae99a56615.hk.png new file mode 100644 index 00000000..4f960870 Binary files /dev/null and b/translated_images/IMG_5335.9f5bfba69a8d5a901c3e3b994a69f62a00d73ef9209b85561553d2ae99a56615.hk.png differ diff --git a/translated_images/IMG_5336.1b46586fdec957670ea71c1bd68c26f73aa95cd5671d057328fd198640729db7.es.png b/translated_images/IMG_5336.1b46586fdec957670ea71c1bd68c26f73aa95cd5671d057328fd198640729db7.es.png new file mode 100644 index 00000000..ca5b5882 Binary files /dev/null and b/translated_images/IMG_5336.1b46586fdec957670ea71c1bd68c26f73aa95cd5671d057328fd198640729db7.es.png differ diff --git a/translated_images/IMG_5336.1b46586fdec957670ea71c1bd68c26f73aa95cd5671d057328fd198640729db7.hk.png b/translated_images/IMG_5336.1b46586fdec957670ea71c1bd68c26f73aa95cd5671d057328fd198640729db7.hk.png new file mode 100644 index 00000000..ca5b5882 Binary files /dev/null and b/translated_images/IMG_5336.1b46586fdec957670ea71c1bd68c26f73aa95cd5671d057328fd198640729db7.hk.png differ diff --git a/translated_images/IMG_5337.91c82be4d37029b03cbb07553d92b9d2dd672e22a07fee6453cbc40568fbdef3.es.png b/translated_images/IMG_5337.91c82be4d37029b03cbb07553d92b9d2dd672e22a07fee6453cbc40568fbdef3.es.png new file mode 100644 index 00000000..2c3440cd Binary files /dev/null and b/translated_images/IMG_5337.91c82be4d37029b03cbb07553d92b9d2dd672e22a07fee6453cbc40568fbdef3.es.png differ diff --git a/translated_images/IMG_5337.91c82be4d37029b03cbb07553d92b9d2dd672e22a07fee6453cbc40568fbdef3.hk.png b/translated_images/IMG_5337.91c82be4d37029b03cbb07553d92b9d2dd672e22a07fee6453cbc40568fbdef3.hk.png new file mode 100644 index 00000000..2c3440cd Binary files /dev/null and b/translated_images/IMG_5337.91c82be4d37029b03cbb07553d92b9d2dd672e22a07fee6453cbc40568fbdef3.hk.png differ diff --git a/translated_images/IMG_5338.9ab356541448923b528f2dedecd72d7ecd07d53cc69118aeb861c39dccb8b8cc.es.png b/translated_images/IMG_5338.9ab356541448923b528f2dedecd72d7ecd07d53cc69118aeb861c39dccb8b8cc.es.png new file mode 100644 index 00000000..5294a9dc Binary files /dev/null and b/translated_images/IMG_5338.9ab356541448923b528f2dedecd72d7ecd07d53cc69118aeb861c39dccb8b8cc.es.png differ diff --git a/translated_images/IMG_5338.9ab356541448923b528f2dedecd72d7ecd07d53cc69118aeb861c39dccb8b8cc.hk.png b/translated_images/IMG_5338.9ab356541448923b528f2dedecd72d7ecd07d53cc69118aeb861c39dccb8b8cc.hk.png new file mode 100644 index 00000000..5294a9dc Binary files /dev/null and b/translated_images/IMG_5338.9ab356541448923b528f2dedecd72d7ecd07d53cc69118aeb861c39dccb8b8cc.hk.png differ diff --git a/translated_images/IMG_5340.8440651b3ce1dd35d9962036330b32a600fb3f59078a581a05c93920c5012b3a.es.png b/translated_images/IMG_5340.8440651b3ce1dd35d9962036330b32a600fb3f59078a581a05c93920c5012b3a.es.png new file mode 100644 index 00000000..912ac4ca Binary files /dev/null and b/translated_images/IMG_5340.8440651b3ce1dd35d9962036330b32a600fb3f59078a581a05c93920c5012b3a.es.png differ diff --git a/translated_images/IMG_5340.8440651b3ce1dd35d9962036330b32a600fb3f59078a581a05c93920c5012b3a.hk.png b/translated_images/IMG_5340.8440651b3ce1dd35d9962036330b32a600fb3f59078a581a05c93920c5012b3a.hk.png new file mode 100644 index 00000000..912ac4ca Binary files /dev/null and b/translated_images/IMG_5340.8440651b3ce1dd35d9962036330b32a600fb3f59078a581a05c93920c5012b3a.hk.png differ diff --git a/translated_images/IMG_5341.a1aa041c42dbc534c033447b06f0546fdd779b3ed5034992ded08a45a960fff5.es.png b/translated_images/IMG_5341.a1aa041c42dbc534c033447b06f0546fdd779b3ed5034992ded08a45a960fff5.es.png new file mode 100644 index 00000000..8e47de7d Binary files /dev/null and b/translated_images/IMG_5341.a1aa041c42dbc534c033447b06f0546fdd779b3ed5034992ded08a45a960fff5.es.png differ diff --git a/translated_images/IMG_5341.a1aa041c42dbc534c033447b06f0546fdd779b3ed5034992ded08a45a960fff5.hk.png b/translated_images/IMG_5341.a1aa041c42dbc534c033447b06f0546fdd779b3ed5034992ded08a45a960fff5.hk.png new file mode 100644 index 00000000..8e47de7d Binary files /dev/null and b/translated_images/IMG_5341.a1aa041c42dbc534c033447b06f0546fdd779b3ed5034992ded08a45a960fff5.hk.png differ diff --git a/translated_images/IMG_5342.9f3b93d9fab90d3b3c1936edb55768b57024c9ebe88a214be315f5ebb083e45d.es.png b/translated_images/IMG_5342.9f3b93d9fab90d3b3c1936edb55768b57024c9ebe88a214be315f5ebb083e45d.es.png new file mode 100644 index 00000000..b3c98d83 Binary files /dev/null and b/translated_images/IMG_5342.9f3b93d9fab90d3b3c1936edb55768b57024c9ebe88a214be315f5ebb083e45d.es.png differ diff --git a/translated_images/IMG_5342.9f3b93d9fab90d3b3c1936edb55768b57024c9ebe88a214be315f5ebb083e45d.hk.png b/translated_images/IMG_5342.9f3b93d9fab90d3b3c1936edb55768b57024c9ebe88a214be315f5ebb083e45d.hk.png new file mode 100644 index 00000000..b3c98d83 Binary files /dev/null and b/translated_images/IMG_5342.9f3b93d9fab90d3b3c1936edb55768b57024c9ebe88a214be315f5ebb083e45d.hk.png differ diff --git a/translated_images/IMG_5343.fa30105d3c10cad2079ca2b2f023e9dab8f82824a235be61837d7e9d09d8d067.es.png b/translated_images/IMG_5343.fa30105d3c10cad2079ca2b2f023e9dab8f82824a235be61837d7e9d09d8d067.es.png new file mode 100644 index 00000000..1d494613 Binary files /dev/null and b/translated_images/IMG_5343.fa30105d3c10cad2079ca2b2f023e9dab8f82824a235be61837d7e9d09d8d067.es.png differ diff --git a/translated_images/IMG_5343.fa30105d3c10cad2079ca2b2f023e9dab8f82824a235be61837d7e9d09d8d067.hk.png b/translated_images/IMG_5343.fa30105d3c10cad2079ca2b2f023e9dab8f82824a235be61837d7e9d09d8d067.hk.png new file mode 100644 index 00000000..1d494613 Binary files /dev/null and b/translated_images/IMG_5343.fa30105d3c10cad2079ca2b2f023e9dab8f82824a235be61837d7e9d09d8d067.hk.png differ diff --git a/translated_images/IMG_5344.acfcd61ee5281321426b2d93efeeb01a60505e73b4c5ee6224c7fa375027b9d8.es.png b/translated_images/IMG_5344.acfcd61ee5281321426b2d93efeeb01a60505e73b4c5ee6224c7fa375027b9d8.es.png new file mode 100644 index 00000000..47ced39a Binary files /dev/null and b/translated_images/IMG_5344.acfcd61ee5281321426b2d93efeeb01a60505e73b4c5ee6224c7fa375027b9d8.es.png differ diff --git a/translated_images/IMG_5344.acfcd61ee5281321426b2d93efeeb01a60505e73b4c5ee6224c7fa375027b9d8.hk.png b/translated_images/IMG_5344.acfcd61ee5281321426b2d93efeeb01a60505e73b4c5ee6224c7fa375027b9d8.hk.png new file mode 100644 index 00000000..47ced39a Binary files /dev/null and b/translated_images/IMG_5344.acfcd61ee5281321426b2d93efeeb01a60505e73b4c5ee6224c7fa375027b9d8.hk.png differ diff --git a/translated_images/IMG_5345.3d305ee2bb4ee8040102a8d1922cdf0450f619c6824add16014a4c0887c18b1d.es.png b/translated_images/IMG_5345.3d305ee2bb4ee8040102a8d1922cdf0450f619c6824add16014a4c0887c18b1d.es.png new file mode 100644 index 00000000..88d5c896 Binary files /dev/null and b/translated_images/IMG_5345.3d305ee2bb4ee8040102a8d1922cdf0450f619c6824add16014a4c0887c18b1d.es.png differ diff --git a/translated_images/IMG_5345.3d305ee2bb4ee8040102a8d1922cdf0450f619c6824add16014a4c0887c18b1d.hk.png b/translated_images/IMG_5345.3d305ee2bb4ee8040102a8d1922cdf0450f619c6824add16014a4c0887c18b1d.hk.png new file mode 100644 index 00000000..88d5c896 Binary files /dev/null and b/translated_images/IMG_5345.3d305ee2bb4ee8040102a8d1922cdf0450f619c6824add16014a4c0887c18b1d.hk.png differ diff --git a/translated_images/IMG_5346.281dcc267f69c70b2bc2353b5e8289617c7bf3608f889dae8a582b9376a9ae7d.es.png b/translated_images/IMG_5346.281dcc267f69c70b2bc2353b5e8289617c7bf3608f889dae8a582b9376a9ae7d.es.png new file mode 100644 index 00000000..e0706533 Binary files /dev/null and b/translated_images/IMG_5346.281dcc267f69c70b2bc2353b5e8289617c7bf3608f889dae8a582b9376a9ae7d.es.png differ diff --git a/translated_images/IMG_5346.281dcc267f69c70b2bc2353b5e8289617c7bf3608f889dae8a582b9376a9ae7d.hk.png b/translated_images/IMG_5346.281dcc267f69c70b2bc2353b5e8289617c7bf3608f889dae8a582b9376a9ae7d.hk.png new file mode 100644 index 00000000..e0706533 Binary files /dev/null and b/translated_images/IMG_5346.281dcc267f69c70b2bc2353b5e8289617c7bf3608f889dae8a582b9376a9ae7d.hk.png differ diff --git a/translated_images/IMG_5347.48a4a981e76910ae1c65bf75102883039be5f0ded32b73f3d09d855f5b7dc977.es.png b/translated_images/IMG_5347.48a4a981e76910ae1c65bf75102883039be5f0ded32b73f3d09d855f5b7dc977.es.png new file mode 100644 index 00000000..a1f17249 Binary files /dev/null and b/translated_images/IMG_5347.48a4a981e76910ae1c65bf75102883039be5f0ded32b73f3d09d855f5b7dc977.es.png differ diff --git a/translated_images/IMG_5347.48a4a981e76910ae1c65bf75102883039be5f0ded32b73f3d09d855f5b7dc977.hk.png b/translated_images/IMG_5347.48a4a981e76910ae1c65bf75102883039be5f0ded32b73f3d09d855f5b7dc977.hk.png new file mode 100644 index 00000000..a1f17249 Binary files /dev/null and b/translated_images/IMG_5347.48a4a981e76910ae1c65bf75102883039be5f0ded32b73f3d09d855f5b7dc977.hk.png differ diff --git a/translated_images/IMG_5348.3961d3b444537c131299f8906dc4e2f7c3c172591ffeacb45719ec3d3718b625.es.png b/translated_images/IMG_5348.3961d3b444537c131299f8906dc4e2f7c3c172591ffeacb45719ec3d3718b625.es.png new file mode 100644 index 00000000..3adc61ef Binary files /dev/null and b/translated_images/IMG_5348.3961d3b444537c131299f8906dc4e2f7c3c172591ffeacb45719ec3d3718b625.es.png differ diff --git a/translated_images/IMG_5348.3961d3b444537c131299f8906dc4e2f7c3c172591ffeacb45719ec3d3718b625.hk.png b/translated_images/IMG_5348.3961d3b444537c131299f8906dc4e2f7c3c172591ffeacb45719ec3d3718b625.hk.png new file mode 100644 index 00000000..3adc61ef Binary files /dev/null and b/translated_images/IMG_5348.3961d3b444537c131299f8906dc4e2f7c3c172591ffeacb45719ec3d3718b625.hk.png differ diff --git a/translated_images/IMG_5349.1f0ec7fbf8807b3bf991dd5400cfb69ded9fe53059bd1e71934f4dbd7ff963db.es.png b/translated_images/IMG_5349.1f0ec7fbf8807b3bf991dd5400cfb69ded9fe53059bd1e71934f4dbd7ff963db.es.png new file mode 100644 index 00000000..1c3c8d53 Binary files /dev/null and b/translated_images/IMG_5349.1f0ec7fbf8807b3bf991dd5400cfb69ded9fe53059bd1e71934f4dbd7ff963db.es.png differ diff --git a/translated_images/IMG_5349.1f0ec7fbf8807b3bf991dd5400cfb69ded9fe53059bd1e71934f4dbd7ff963db.hk.png b/translated_images/IMG_5349.1f0ec7fbf8807b3bf991dd5400cfb69ded9fe53059bd1e71934f4dbd7ff963db.hk.png new file mode 100644 index 00000000..1c3c8d53 Binary files /dev/null and b/translated_images/IMG_5349.1f0ec7fbf8807b3bf991dd5400cfb69ded9fe53059bd1e71934f4dbd7ff963db.hk.png differ diff --git a/translated_images/Roadmap.bb1dec285dda0eda691788b95ddfc96d31d76bb7649e3f04a135e4ad395f323e.es.jpg b/translated_images/Roadmap.bb1dec285dda0eda691788b95ddfc96d31d76bb7649e3f04a135e4ad395f323e.es.jpg new file mode 100644 index 00000000..0f4a9a38 Binary files /dev/null and b/translated_images/Roadmap.bb1dec285dda0eda691788b95ddfc96d31d76bb7649e3f04a135e4ad395f323e.es.jpg differ diff --git a/translated_images/Roadmap.bb1dec285dda0eda691788b95ddfc96d31d76bb7649e3f04a135e4ad395f323e.hk.jpg b/translated_images/Roadmap.bb1dec285dda0eda691788b95ddfc96d31d76bb7649e3f04a135e4ad395f323e.hk.jpg new file mode 100644 index 00000000..0f4a9a38 Binary files /dev/null and b/translated_images/Roadmap.bb1dec285dda0eda691788b95ddfc96d31d76bb7649e3f04a135e4ad395f323e.hk.jpg differ diff --git a/translated_images/amqp.804bd4fce83301578f19af1b877f8ce87a6473a3616fb6c3f901fe4041ab6c96.es.png b/translated_images/amqp.804bd4fce83301578f19af1b877f8ce87a6473a3616fb6c3f901fe4041ab6c96.es.png new file mode 100644 index 00000000..32dab60c Binary files /dev/null and b/translated_images/amqp.804bd4fce83301578f19af1b877f8ce87a6473a3616fb6c3f901fe4041ab6c96.es.png differ diff --git a/translated_images/amqp.804bd4fce83301578f19af1b877f8ce87a6473a3616fb6c3f901fe4041ab6c96.hk.png b/translated_images/amqp.804bd4fce83301578f19af1b877f8ce87a6473a3616fb6c3f901fe4041ab6c96.hk.png new file mode 100644 index 00000000..32dab60c Binary files /dev/null and b/translated_images/amqp.804bd4fce83301578f19af1b877f8ce87a6473a3616fb6c3f901fe4041ab6c96.hk.png differ diff --git a/translated_images/analog-sensor-voltage.3b6f3153922473997cae6f71a6110d89a020a8a1838a83fba4f97e8fa6cef3ac.es.png b/translated_images/analog-sensor-voltage.3b6f3153922473997cae6f71a6110d89a020a8a1838a83fba4f97e8fa6cef3ac.es.png new file mode 100644 index 00000000..78e9b675 Binary files /dev/null and b/translated_images/analog-sensor-voltage.3b6f3153922473997cae6f71a6110d89a020a8a1838a83fba4f97e8fa6cef3ac.es.png differ diff --git a/translated_images/analog-sensor-voltage.3b6f3153922473997cae6f71a6110d89a020a8a1838a83fba4f97e8fa6cef3ac.hk.png b/translated_images/analog-sensor-voltage.3b6f3153922473997cae6f71a6110d89a020a8a1838a83fba4f97e8fa6cef3ac.hk.png new file mode 100644 index 00000000..78e9b675 Binary files /dev/null and b/translated_images/analog-sensor-voltage.3b6f3153922473997cae6f71a6110d89a020a8a1838a83fba4f97e8fa6cef3ac.hk.png differ diff --git a/translated_images/arducam-wio-terminal-connections.a4d5a4049bdb5ab800a2877389fc6ecf5e4ff307e6451ff56c517e6786467d0a.es.png b/translated_images/arducam-wio-terminal-connections.a4d5a4049bdb5ab800a2877389fc6ecf5e4ff307e6451ff56c517e6786467d0a.es.png new file mode 100644 index 00000000..fb87dd71 Binary files /dev/null and b/translated_images/arducam-wio-terminal-connections.a4d5a4049bdb5ab800a2877389fc6ecf5e4ff307e6451ff56c517e6786467d0a.es.png differ diff --git a/translated_images/arducam-wio-terminal-connections.a4d5a4049bdb5ab800a2877389fc6ecf5e4ff307e6451ff56c517e6786467d0a.hk.png b/translated_images/arducam-wio-terminal-connections.a4d5a4049bdb5ab800a2877389fc6ecf5e4ff307e6451ff56c517e6786467d0a.hk.png new file mode 100644 index 00000000..fb87dd71 Binary files /dev/null and b/translated_images/arducam-wio-terminal-connections.a4d5a4049bdb5ab800a2877389fc6ecf5e4ff307e6451ff56c517e6786467d0a.hk.png differ diff --git a/translated_images/arducam.20e4e4cbb268296570b5914e20d6c349fc42ddac9ed4e1b9deba2188204eebae.es.png b/translated_images/arducam.20e4e4cbb268296570b5914e20d6c349fc42ddac9ed4e1b9deba2188204eebae.es.png new file mode 100644 index 00000000..acaa9a02 Binary files /dev/null and b/translated_images/arducam.20e4e4cbb268296570b5914e20d6c349fc42ddac9ed4e1b9deba2188204eebae.es.png differ diff --git a/translated_images/arducam.20e4e4cbb268296570b5914e20d6c349fc42ddac9ed4e1b9deba2188204eebae.hk.png b/translated_images/arducam.20e4e4cbb268296570b5914e20d6c349fc42ddac9ed4e1b9deba2188204eebae.hk.png new file mode 100644 index 00000000..acaa9a02 Binary files /dev/null and b/translated_images/arducam.20e4e4cbb268296570b5914e20d6c349fc42ddac9ed4e1b9deba2188204eebae.hk.png differ diff --git a/translated_images/arduino-sketch.79590cb837ff7a7c6a68d1afda6cab83fd53d3bb1bd9a8bf2eaf8d693a4d3ea6.es.png b/translated_images/arduino-sketch.79590cb837ff7a7c6a68d1afda6cab83fd53d3bb1bd9a8bf2eaf8d693a4d3ea6.es.png new file mode 100644 index 00000000..b6afaa8a Binary files /dev/null and b/translated_images/arduino-sketch.79590cb837ff7a7c6a68d1afda6cab83fd53d3bb1bd9a8bf2eaf8d693a4d3ea6.es.png differ diff --git a/translated_images/arduino-sketch.79590cb837ff7a7c6a68d1afda6cab83fd53d3bb1bd9a8bf2eaf8d693a4d3ea6.hk.png b/translated_images/arduino-sketch.79590cb837ff7a7c6a68d1afda6cab83fd53d3bb1bd9a8bf2eaf8d693a4d3ea6.hk.png new file mode 100644 index 00000000..b6afaa8a Binary files /dev/null and b/translated_images/arduino-sketch.79590cb837ff7a7c6a68d1afda6cab83fd53d3bb1bd9a8bf2eaf8d693a4d3ea6.hk.png differ diff --git a/translated_images/assignment-1-flow.7552a51acb1a5ec858dca6e855cdbb44206434006df8ba3799a25afcdab1665d.es.png b/translated_images/assignment-1-flow.7552a51acb1a5ec858dca6e855cdbb44206434006df8ba3799a25afcdab1665d.es.png new file mode 100644 index 00000000..18f92ede Binary files /dev/null and b/translated_images/assignment-1-flow.7552a51acb1a5ec858dca6e855cdbb44206434006df8ba3799a25afcdab1665d.es.png differ diff --git a/translated_images/assignment-1-flow.7552a51acb1a5ec858dca6e855cdbb44206434006df8ba3799a25afcdab1665d.hk.png b/translated_images/assignment-1-flow.7552a51acb1a5ec858dca6e855cdbb44206434006df8ba3799a25afcdab1665d.hk.png new file mode 100644 index 00000000..18f92ede Binary files /dev/null and b/translated_images/assignment-1-flow.7552a51acb1a5ec858dca6e855cdbb44206434006df8ba3799a25afcdab1665d.hk.png differ diff --git a/translated_images/assignment-1-internet-flow.3256feab5f052fd273bf4e331157c574c2c3fa42e479836fc9c3586f41db35a5.es.png b/translated_images/assignment-1-internet-flow.3256feab5f052fd273bf4e331157c574c2c3fa42e479836fc9c3586f41db35a5.es.png new file mode 100644 index 00000000..e1eb6df0 Binary files /dev/null and b/translated_images/assignment-1-internet-flow.3256feab5f052fd273bf4e331157c574c2c3fa42e479836fc9c3586f41db35a5.es.png differ diff --git a/translated_images/assignment-1-internet-flow.3256feab5f052fd273bf4e331157c574c2c3fa42e479836fc9c3586f41db35a5.hk.png b/translated_images/assignment-1-internet-flow.3256feab5f052fd273bf4e331157c574c2c3fa42e479836fc9c3586f41db35a5.hk.png new file mode 100644 index 00000000..e1eb6df0 Binary files /dev/null and b/translated_images/assignment-1-internet-flow.3256feab5f052fd273bf4e331157c574c2c3fa42e479836fc9c3586f41db35a5.hk.png differ diff --git a/translated_images/azure-container-registry-logo.09494206991d4b295025ebff7d4e2900325e527a59184ffbc8464b6ab59654be.es.png b/translated_images/azure-container-registry-logo.09494206991d4b295025ebff7d4e2900325e527a59184ffbc8464b6ab59654be.es.png new file mode 100644 index 00000000..dfcfde45 Binary files /dev/null and b/translated_images/azure-container-registry-logo.09494206991d4b295025ebff7d4e2900325e527a59184ffbc8464b6ab59654be.es.png differ diff --git a/translated_images/azure-container-registry-logo.09494206991d4b295025ebff7d4e2900325e527a59184ffbc8464b6ab59654be.hk.png b/translated_images/azure-container-registry-logo.09494206991d4b295025ebff7d4e2900325e527a59184ffbc8464b6ab59654be.hk.png new file mode 100644 index 00000000..dfcfde45 Binary files /dev/null and b/translated_images/azure-container-registry-logo.09494206991d4b295025ebff7d4e2900325e527a59184ffbc8464b6ab59654be.hk.png differ diff --git a/translated_images/azure-functions-logo.1cfc8e3204c9c44aaf80fcf406fc8544d80d7f00f8d3e8ed6fed764563e17564.es.png b/translated_images/azure-functions-logo.1cfc8e3204c9c44aaf80fcf406fc8544d80d7f00f8d3e8ed6fed764563e17564.es.png new file mode 100644 index 00000000..44af1896 Binary files /dev/null and b/translated_images/azure-functions-logo.1cfc8e3204c9c44aaf80fcf406fc8544d80d7f00f8d3e8ed6fed764563e17564.es.png differ diff --git a/translated_images/azure-functions-logo.1cfc8e3204c9c44aaf80fcf406fc8544d80d7f00f8d3e8ed6fed764563e17564.hk.png b/translated_images/azure-functions-logo.1cfc8e3204c9c44aaf80fcf406fc8544d80d7f00f8d3e8ed6fed764563e17564.hk.png new file mode 100644 index 00000000..44af1896 Binary files /dev/null and b/translated_images/azure-functions-logo.1cfc8e3204c9c44aaf80fcf406fc8544d80d7f00f8d3e8ed6fed764563e17564.hk.png differ diff --git a/translated_images/azure-iot-edge-logo.c1c076749b5cba2e8755262fadc2f19ca1146b948d76990b1229199ac2292d79.es.png b/translated_images/azure-iot-edge-logo.c1c076749b5cba2e8755262fadc2f19ca1146b948d76990b1229199ac2292d79.es.png new file mode 100644 index 00000000..6d749e6c Binary files /dev/null and b/translated_images/azure-iot-edge-logo.c1c076749b5cba2e8755262fadc2f19ca1146b948d76990b1229199ac2292d79.es.png differ diff --git a/translated_images/azure-iot-edge-logo.c1c076749b5cba2e8755262fadc2f19ca1146b948d76990b1229199ac2292d79.hk.png b/translated_images/azure-iot-edge-logo.c1c076749b5cba2e8755262fadc2f19ca1146b948d76990b1229199ac2292d79.hk.png new file mode 100644 index 00000000..6d749e6c Binary files /dev/null and b/translated_images/azure-iot-edge-logo.c1c076749b5cba2e8755262fadc2f19ca1146b948d76990b1229199ac2292d79.hk.png differ diff --git a/translated_images/azure-iot-hub-logo.28a19de76d0a1932464d858f7558712bcdace3e5ec69c434d482ed7ce41c3a26.es.png b/translated_images/azure-iot-hub-logo.28a19de76d0a1932464d858f7558712bcdace3e5ec69c434d482ed7ce41c3a26.es.png new file mode 100644 index 00000000..7485e36c Binary files /dev/null and b/translated_images/azure-iot-hub-logo.28a19de76d0a1932464d858f7558712bcdace3e5ec69c434d482ed7ce41c3a26.es.png differ diff --git a/translated_images/azure-iot-hub-logo.28a19de76d0a1932464d858f7558712bcdace3e5ec69c434d482ed7ce41c3a26.hk.png b/translated_images/azure-iot-hub-logo.28a19de76d0a1932464d858f7558712bcdace3e5ec69c434d482ed7ce41c3a26.hk.png new file mode 100644 index 00000000..7485e36c Binary files /dev/null and b/translated_images/azure-iot-hub-logo.28a19de76d0a1932464d858f7558712bcdace3e5ec69c434d482ed7ce41c3a26.hk.png differ diff --git a/translated_images/azure-maps-logo.35d01dcfbd81fe6140e94257aaa1538f785a58c91576d14e0ebe7a2f6c694b99.es.png b/translated_images/azure-maps-logo.35d01dcfbd81fe6140e94257aaa1538f785a58c91576d14e0ebe7a2f6c694b99.es.png new file mode 100644 index 00000000..0f499097 Binary files /dev/null and b/translated_images/azure-maps-logo.35d01dcfbd81fe6140e94257aaa1538f785a58c91576d14e0ebe7a2f6c694b99.es.png differ diff --git a/translated_images/azure-maps-logo.35d01dcfbd81fe6140e94257aaa1538f785a58c91576d14e0ebe7a2f6c694b99.hk.png b/translated_images/azure-maps-logo.35d01dcfbd81fe6140e94257aaa1538f785a58c91576d14e0ebe7a2f6c694b99.hk.png new file mode 100644 index 00000000..0f499097 Binary files /dev/null and b/translated_images/azure-maps-logo.35d01dcfbd81fe6140e94257aaa1538f785a58c91576d14e0ebe7a2f6c694b99.hk.png differ diff --git a/translated_images/azure-region-existing.73f704604f2aa6cb9b5a49ed40e93d4fd81ae3f4e6af4a8ca504023902832f56.es.png b/translated_images/azure-region-existing.73f704604f2aa6cb9b5a49ed40e93d4fd81ae3f4e6af4a8ca504023902832f56.es.png new file mode 100644 index 00000000..710c440c Binary files /dev/null and b/translated_images/azure-region-existing.73f704604f2aa6cb9b5a49ed40e93d4fd81ae3f4e6af4a8ca504023902832f56.es.png differ diff --git a/translated_images/azure-region-existing.73f704604f2aa6cb9b5a49ed40e93d4fd81ae3f4e6af4a8ca504023902832f56.hk.png b/translated_images/azure-region-existing.73f704604f2aa6cb9b5a49ed40e93d4fd81ae3f4e6af4a8ca504023902832f56.hk.png new file mode 100644 index 00000000..710c440c Binary files /dev/null and b/translated_images/azure-region-existing.73f704604f2aa6cb9b5a49ed40e93d4fd81ae3f4e6af4a8ca504023902832f56.hk.png differ diff --git a/translated_images/azure-region-planned-expansion.a5074a1e8af74f156a73552d502429e5b126ea5019274d767ecb4b9afdad442b.es.png b/translated_images/azure-region-planned-expansion.a5074a1e8af74f156a73552d502429e5b126ea5019274d767ecb4b9afdad442b.es.png new file mode 100644 index 00000000..24cecced Binary files /dev/null and b/translated_images/azure-region-planned-expansion.a5074a1e8af74f156a73552d502429e5b126ea5019274d767ecb4b9afdad442b.es.png differ diff --git a/translated_images/azure-region-planned-expansion.a5074a1e8af74f156a73552d502429e5b126ea5019274d767ecb4b9afdad442b.hk.png b/translated_images/azure-region-planned-expansion.a5074a1e8af74f156a73552d502429e5b126ea5019274d767ecb4b9afdad442b.hk.png new file mode 100644 index 00000000..24cecced Binary files /dev/null and b/translated_images/azure-region-planned-expansion.a5074a1e8af74f156a73552d502429e5b126ea5019274d767ecb4b9afdad442b.hk.png differ diff --git a/translated_images/azure-speech-logo.a1f08c4befb0159f2cb5d692d3baf5b599e7b44759d316da907bda1508f46a4a.es.png b/translated_images/azure-speech-logo.a1f08c4befb0159f2cb5d692d3baf5b599e7b44759d316da907bda1508f46a4a.es.png new file mode 100644 index 00000000..b36025d9 Binary files /dev/null and b/translated_images/azure-speech-logo.a1f08c4befb0159f2cb5d692d3baf5b599e7b44759d316da907bda1508f46a4a.es.png differ diff --git a/translated_images/azure-speech-logo.a1f08c4befb0159f2cb5d692d3baf5b599e7b44759d316da907bda1508f46a4a.hk.png b/translated_images/azure-speech-logo.a1f08c4befb0159f2cb5d692d3baf5b599e7b44759d316da907bda1508f46a4a.hk.png new file mode 100644 index 00000000..b36025d9 Binary files /dev/null and b/translated_images/azure-speech-logo.a1f08c4befb0159f2cb5d692d3baf5b599e7b44759d316da907bda1508f46a4a.hk.png differ diff --git a/translated_images/azure-storage-logo.605c0f602c640d482a80f1b35a2629a32d595711b7ab1d7ceea843250615ff32.es.png b/translated_images/azure-storage-logo.605c0f602c640d482a80f1b35a2629a32d595711b7ab1d7ceea843250615ff32.es.png new file mode 100644 index 00000000..b21a4bed Binary files /dev/null and b/translated_images/azure-storage-logo.605c0f602c640d482a80f1b35a2629a32d595711b7ab1d7ceea843250615ff32.es.png differ diff --git a/translated_images/azure-storage-logo.605c0f602c640d482a80f1b35a2629a32d595711b7ab1d7ceea843250615ff32.hk.png b/translated_images/azure-storage-logo.605c0f602c640d482a80f1b35a2629a32d595711b7ab1d7ceea843250615ff32.hk.png new file mode 100644 index 00000000..b21a4bed Binary files /dev/null and b/translated_images/azure-storage-logo.605c0f602c640d482a80f1b35a2629a32d595711b7ab1d7ceea843250615ff32.hk.png differ diff --git a/translated_images/azure-translator-logo.c6ed3a4a433edfd2f11577eca105412c50b8396b194cbbd730723dd1d0793bcd.es.png b/translated_images/azure-translator-logo.c6ed3a4a433edfd2f11577eca105412c50b8396b194cbbd730723dd1d0793bcd.es.png new file mode 100644 index 00000000..8da6f9a4 Binary files /dev/null and b/translated_images/azure-translator-logo.c6ed3a4a433edfd2f11577eca105412c50b8396b194cbbd730723dd1d0793bcd.es.png differ diff --git a/translated_images/azure-translator-logo.c6ed3a4a433edfd2f11577eca105412c50b8396b194cbbd730723dd1d0793bcd.hk.png b/translated_images/azure-translator-logo.c6ed3a4a433edfd2f11577eca105412c50b8396b194cbbd730723dd1d0793bcd.hk.png new file mode 100644 index 00000000..8da6f9a4 Binary files /dev/null and b/translated_images/azure-translator-logo.c6ed3a4a433edfd2f11577eca105412c50b8396b194cbbd730723dd1d0793bcd.hk.png differ diff --git a/translated_images/banana-arducam.be1b32d4267a8194b0fd042362e56faa431da9cd4af172051b37243ea9be0256.es.jpg b/translated_images/banana-arducam.be1b32d4267a8194b0fd042362e56faa431da9cd4af172051b37243ea9be0256.es.jpg new file mode 100644 index 00000000..437f3d07 Binary files /dev/null and b/translated_images/banana-arducam.be1b32d4267a8194b0fd042362e56faa431da9cd4af172051b37243ea9be0256.es.jpg differ diff --git a/translated_images/banana-arducam.be1b32d4267a8194b0fd042362e56faa431da9cd4af172051b37243ea9be0256.hk.jpg b/translated_images/banana-arducam.be1b32d4267a8194b0fd042362e56faa431da9cd4af172051b37243ea9be0256.hk.jpg new file mode 100644 index 00000000..437f3d07 Binary files /dev/null and b/translated_images/banana-arducam.be1b32d4267a8194b0fd042362e56faa431da9cd4af172051b37243ea9be0256.hk.jpg differ diff --git a/translated_images/banana-picture-compare.174df164dc326a42cf7fb051a7497e6113c620e91552d92ca914220305d47d9a.es.png b/translated_images/banana-picture-compare.174df164dc326a42cf7fb051a7497e6113c620e91552d92ca914220305d47d9a.es.png new file mode 100644 index 00000000..cc61fb13 Binary files /dev/null and b/translated_images/banana-picture-compare.174df164dc326a42cf7fb051a7497e6113c620e91552d92ca914220305d47d9a.es.png differ diff --git a/translated_images/banana-picture-compare.174df164dc326a42cf7fb051a7497e6113c620e91552d92ca914220305d47d9a.hk.png b/translated_images/banana-picture-compare.174df164dc326a42cf7fb051a7497e6113c620e91552d92ca914220305d47d9a.hk.png new file mode 100644 index 00000000..cc61fb13 Binary files /dev/null and b/translated_images/banana-picture-compare.174df164dc326a42cf7fb051a7497e6113c620e91552d92ca914220305d47d9a.hk.png differ diff --git a/translated_images/banana-ripe-1.6ed72365ffc9230064fbaefdb698bde74529ad5b3c747a4a28421b534730fa5f.es.png b/translated_images/banana-ripe-1.6ed72365ffc9230064fbaefdb698bde74529ad5b3c747a4a28421b534730fa5f.es.png new file mode 100644 index 00000000..3472b1d9 Binary files /dev/null and b/translated_images/banana-ripe-1.6ed72365ffc9230064fbaefdb698bde74529ad5b3c747a4a28421b534730fa5f.es.png differ diff --git a/translated_images/banana-ripe-1.6ed72365ffc9230064fbaefdb698bde74529ad5b3c747a4a28421b534730fa5f.hk.png b/translated_images/banana-ripe-1.6ed72365ffc9230064fbaefdb698bde74529ad5b3c747a4a28421b534730fa5f.hk.png new file mode 100644 index 00000000..3472b1d9 Binary files /dev/null and b/translated_images/banana-ripe-1.6ed72365ffc9230064fbaefdb698bde74529ad5b3c747a4a28421b534730fa5f.hk.png differ diff --git a/translated_images/banana-ripe-1.780e9be3a60d8879826126ee1e84e135ffa20ec91697bb759daf7ba0b76c811b.es.png b/translated_images/banana-ripe-1.780e9be3a60d8879826126ee1e84e135ffa20ec91697bb759daf7ba0b76c811b.es.png new file mode 100644 index 00000000..0bbca602 Binary files /dev/null and b/translated_images/banana-ripe-1.780e9be3a60d8879826126ee1e84e135ffa20ec91697bb759daf7ba0b76c811b.es.png differ diff --git a/translated_images/banana-ripe-1.780e9be3a60d8879826126ee1e84e135ffa20ec91697bb759daf7ba0b76c811b.hk.png b/translated_images/banana-ripe-1.780e9be3a60d8879826126ee1e84e135ffa20ec91697bb759daf7ba0b76c811b.hk.png new file mode 100644 index 00000000..0bbca602 Binary files /dev/null and b/translated_images/banana-ripe-1.780e9be3a60d8879826126ee1e84e135ffa20ec91697bb759daf7ba0b76c811b.hk.png differ diff --git a/translated_images/banana-ripe-10.c3d98eb280e7464ffa36da1fa18413db4fd032da973b098bb4978d6d99c1a3af.es.png b/translated_images/banana-ripe-10.c3d98eb280e7464ffa36da1fa18413db4fd032da973b098bb4978d6d99c1a3af.es.png new file mode 100644 index 00000000..b5775adc Binary files /dev/null and b/translated_images/banana-ripe-10.c3d98eb280e7464ffa36da1fa18413db4fd032da973b098bb4978d6d99c1a3af.es.png differ diff --git a/translated_images/banana-ripe-10.c3d98eb280e7464ffa36da1fa18413db4fd032da973b098bb4978d6d99c1a3af.hk.png b/translated_images/banana-ripe-10.c3d98eb280e7464ffa36da1fa18413db4fd032da973b098bb4978d6d99c1a3af.hk.png new file mode 100644 index 00000000..b5775adc Binary files /dev/null and b/translated_images/banana-ripe-10.c3d98eb280e7464ffa36da1fa18413db4fd032da973b098bb4978d6d99c1a3af.hk.png differ diff --git a/translated_images/banana-ripe-11.3d932f292b95b9a202082ce75f5b52ecaf43718721661810b53f7a5a2c4b4133.es.png b/translated_images/banana-ripe-11.3d932f292b95b9a202082ce75f5b52ecaf43718721661810b53f7a5a2c4b4133.es.png new file mode 100644 index 00000000..bc58477a Binary files /dev/null and b/translated_images/banana-ripe-11.3d932f292b95b9a202082ce75f5b52ecaf43718721661810b53f7a5a2c4b4133.es.png differ diff --git a/translated_images/banana-ripe-11.3d932f292b95b9a202082ce75f5b52ecaf43718721661810b53f7a5a2c4b4133.hk.png b/translated_images/banana-ripe-11.3d932f292b95b9a202082ce75f5b52ecaf43718721661810b53f7a5a2c4b4133.hk.png new file mode 100644 index 00000000..bc58477a Binary files /dev/null and b/translated_images/banana-ripe-11.3d932f292b95b9a202082ce75f5b52ecaf43718721661810b53f7a5a2c4b4133.hk.png differ diff --git a/translated_images/banana-ripe-12.9f87e663b9da6c8525f3ce63c5c0a1c095e42675e2a6af9b0fddb14ebb1e0b4b.es.png b/translated_images/banana-ripe-12.9f87e663b9da6c8525f3ce63c5c0a1c095e42675e2a6af9b0fddb14ebb1e0b4b.es.png new file mode 100644 index 00000000..1b7a40f4 Binary files /dev/null and b/translated_images/banana-ripe-12.9f87e663b9da6c8525f3ce63c5c0a1c095e42675e2a6af9b0fddb14ebb1e0b4b.es.png differ diff --git a/translated_images/banana-ripe-12.9f87e663b9da6c8525f3ce63c5c0a1c095e42675e2a6af9b0fddb14ebb1e0b4b.hk.png b/translated_images/banana-ripe-12.9f87e663b9da6c8525f3ce63c5c0a1c095e42675e2a6af9b0fddb14ebb1e0b4b.hk.png new file mode 100644 index 00000000..1b7a40f4 Binary files /dev/null and b/translated_images/banana-ripe-12.9f87e663b9da6c8525f3ce63c5c0a1c095e42675e2a6af9b0fddb14ebb1e0b4b.hk.png differ diff --git a/translated_images/banana-ripe-13.b7402e05160f454309533a578849d7e79f92dd70799428943d7211c2fbb82465.es.png b/translated_images/banana-ripe-13.b7402e05160f454309533a578849d7e79f92dd70799428943d7211c2fbb82465.es.png new file mode 100644 index 00000000..011b07a3 Binary files /dev/null and b/translated_images/banana-ripe-13.b7402e05160f454309533a578849d7e79f92dd70799428943d7211c2fbb82465.es.png differ diff --git a/translated_images/banana-ripe-13.b7402e05160f454309533a578849d7e79f92dd70799428943d7211c2fbb82465.hk.png b/translated_images/banana-ripe-13.b7402e05160f454309533a578849d7e79f92dd70799428943d7211c2fbb82465.hk.png new file mode 100644 index 00000000..011b07a3 Binary files /dev/null and b/translated_images/banana-ripe-13.b7402e05160f454309533a578849d7e79f92dd70799428943d7211c2fbb82465.hk.png differ diff --git a/translated_images/banana-ripe-14.85cf309aa702cfa870286a5f8838ee5875a655074a982bafe5b8d32d4d5819f2.es.png b/translated_images/banana-ripe-14.85cf309aa702cfa870286a5f8838ee5875a655074a982bafe5b8d32d4d5819f2.es.png new file mode 100644 index 00000000..7f9d24ef Binary files /dev/null and b/translated_images/banana-ripe-14.85cf309aa702cfa870286a5f8838ee5875a655074a982bafe5b8d32d4d5819f2.es.png differ diff --git a/translated_images/banana-ripe-14.85cf309aa702cfa870286a5f8838ee5875a655074a982bafe5b8d32d4d5819f2.hk.png b/translated_images/banana-ripe-14.85cf309aa702cfa870286a5f8838ee5875a655074a982bafe5b8d32d4d5819f2.hk.png new file mode 100644 index 00000000..7f9d24ef Binary files /dev/null and b/translated_images/banana-ripe-14.85cf309aa702cfa870286a5f8838ee5875a655074a982bafe5b8d32d4d5819f2.hk.png differ diff --git a/translated_images/banana-ripe-15.933412eb14a3f8e419c764c8157d1e5f25256972a8dcf450aa630b8c007c8c3d.es.png b/translated_images/banana-ripe-15.933412eb14a3f8e419c764c8157d1e5f25256972a8dcf450aa630b8c007c8c3d.es.png new file mode 100644 index 00000000..0c6a7067 Binary files /dev/null and b/translated_images/banana-ripe-15.933412eb14a3f8e419c764c8157d1e5f25256972a8dcf450aa630b8c007c8c3d.es.png differ diff --git a/translated_images/banana-ripe-15.933412eb14a3f8e419c764c8157d1e5f25256972a8dcf450aa630b8c007c8c3d.hk.png b/translated_images/banana-ripe-15.933412eb14a3f8e419c764c8157d1e5f25256972a8dcf450aa630b8c007c8c3d.hk.png new file mode 100644 index 00000000..0c6a7067 Binary files /dev/null and b/translated_images/banana-ripe-15.933412eb14a3f8e419c764c8157d1e5f25256972a8dcf450aa630b8c007c8c3d.hk.png differ diff --git a/translated_images/banana-ripe-16.781a68a01401f89e5e523c88e659a0f9697b7de378571c91e597edc0d0c2eb07.es.png b/translated_images/banana-ripe-16.781a68a01401f89e5e523c88e659a0f9697b7de378571c91e597edc0d0c2eb07.es.png new file mode 100644 index 00000000..8f7968a5 Binary files /dev/null and b/translated_images/banana-ripe-16.781a68a01401f89e5e523c88e659a0f9697b7de378571c91e597edc0d0c2eb07.es.png differ diff --git a/translated_images/banana-ripe-16.781a68a01401f89e5e523c88e659a0f9697b7de378571c91e597edc0d0c2eb07.hk.png b/translated_images/banana-ripe-16.781a68a01401f89e5e523c88e659a0f9697b7de378571c91e597edc0d0c2eb07.hk.png new file mode 100644 index 00000000..8f7968a5 Binary files /dev/null and b/translated_images/banana-ripe-16.781a68a01401f89e5e523c88e659a0f9697b7de378571c91e597edc0d0c2eb07.hk.png differ diff --git a/translated_images/banana-ripe-17.f8e2853a40d3ac450e290036792b75ac4b8da5883536478722fb336d5f66517e.es.png b/translated_images/banana-ripe-17.f8e2853a40d3ac450e290036792b75ac4b8da5883536478722fb336d5f66517e.es.png new file mode 100644 index 00000000..20c6036f Binary files /dev/null and b/translated_images/banana-ripe-17.f8e2853a40d3ac450e290036792b75ac4b8da5883536478722fb336d5f66517e.es.png differ diff --git a/translated_images/banana-ripe-17.f8e2853a40d3ac450e290036792b75ac4b8da5883536478722fb336d5f66517e.hk.png b/translated_images/banana-ripe-17.f8e2853a40d3ac450e290036792b75ac4b8da5883536478722fb336d5f66517e.hk.png new file mode 100644 index 00000000..20c6036f Binary files /dev/null and b/translated_images/banana-ripe-17.f8e2853a40d3ac450e290036792b75ac4b8da5883536478722fb336d5f66517e.hk.png differ diff --git a/translated_images/banana-ripe-18.3d05f5f78ecf6f0d74aecdafb8e415851a5333e5dbc016ac1870ab5e4c383b07.es.png b/translated_images/banana-ripe-18.3d05f5f78ecf6f0d74aecdafb8e415851a5333e5dbc016ac1870ab5e4c383b07.es.png new file mode 100644 index 00000000..f077b6e9 Binary files /dev/null and b/translated_images/banana-ripe-18.3d05f5f78ecf6f0d74aecdafb8e415851a5333e5dbc016ac1870ab5e4c383b07.es.png differ diff --git a/translated_images/banana-ripe-18.3d05f5f78ecf6f0d74aecdafb8e415851a5333e5dbc016ac1870ab5e4c383b07.hk.png b/translated_images/banana-ripe-18.3d05f5f78ecf6f0d74aecdafb8e415851a5333e5dbc016ac1870ab5e4c383b07.hk.png new file mode 100644 index 00000000..f077b6e9 Binary files /dev/null and b/translated_images/banana-ripe-18.3d05f5f78ecf6f0d74aecdafb8e415851a5333e5dbc016ac1870ab5e4c383b07.hk.png differ diff --git a/translated_images/banana-ripe-19.ac3b0fc6cf6fdfd5523227bc246c915b228bc3d4bc1c72f6612723ed889023b5.es.png b/translated_images/banana-ripe-19.ac3b0fc6cf6fdfd5523227bc246c915b228bc3d4bc1c72f6612723ed889023b5.es.png new file mode 100644 index 00000000..484206d5 Binary files /dev/null and b/translated_images/banana-ripe-19.ac3b0fc6cf6fdfd5523227bc246c915b228bc3d4bc1c72f6612723ed889023b5.es.png differ diff --git a/translated_images/banana-ripe-19.ac3b0fc6cf6fdfd5523227bc246c915b228bc3d4bc1c72f6612723ed889023b5.hk.png b/translated_images/banana-ripe-19.ac3b0fc6cf6fdfd5523227bc246c915b228bc3d4bc1c72f6612723ed889023b5.hk.png new file mode 100644 index 00000000..484206d5 Binary files /dev/null and b/translated_images/banana-ripe-19.ac3b0fc6cf6fdfd5523227bc246c915b228bc3d4bc1c72f6612723ed889023b5.hk.png differ diff --git a/translated_images/banana-ripe-2.8ab96da692df69f1c78bd3a93acfdb17bc292ac964a3f3bac9249ba1dd1681c3.es.png b/translated_images/banana-ripe-2.8ab96da692df69f1c78bd3a93acfdb17bc292ac964a3f3bac9249ba1dd1681c3.es.png new file mode 100644 index 00000000..9fa156e2 Binary files /dev/null and b/translated_images/banana-ripe-2.8ab96da692df69f1c78bd3a93acfdb17bc292ac964a3f3bac9249ba1dd1681c3.es.png differ diff --git a/translated_images/banana-ripe-2.8ab96da692df69f1c78bd3a93acfdb17bc292ac964a3f3bac9249ba1dd1681c3.hk.png b/translated_images/banana-ripe-2.8ab96da692df69f1c78bd3a93acfdb17bc292ac964a3f3bac9249ba1dd1681c3.hk.png new file mode 100644 index 00000000..9fa156e2 Binary files /dev/null and b/translated_images/banana-ripe-2.8ab96da692df69f1c78bd3a93acfdb17bc292ac964a3f3bac9249ba1dd1681c3.hk.png differ diff --git a/translated_images/banana-ripe-2.96ddc53114c5f020a328b264174eef43d2096620c6b10ff5189e99674c1dfa8c.es.png b/translated_images/banana-ripe-2.96ddc53114c5f020a328b264174eef43d2096620c6b10ff5189e99674c1dfa8c.es.png new file mode 100644 index 00000000..b0813972 Binary files /dev/null and b/translated_images/banana-ripe-2.96ddc53114c5f020a328b264174eef43d2096620c6b10ff5189e99674c1dfa8c.es.png differ diff --git a/translated_images/banana-ripe-2.96ddc53114c5f020a328b264174eef43d2096620c6b10ff5189e99674c1dfa8c.hk.png b/translated_images/banana-ripe-2.96ddc53114c5f020a328b264174eef43d2096620c6b10ff5189e99674c1dfa8c.hk.png new file mode 100644 index 00000000..b0813972 Binary files /dev/null and b/translated_images/banana-ripe-2.96ddc53114c5f020a328b264174eef43d2096620c6b10ff5189e99674c1dfa8c.hk.png differ diff --git a/translated_images/banana-ripe-20.a4d0ad33a7e6f037ac9276dc751ae62d56d3cc16e625837197ef49da426bc3c8.es.png b/translated_images/banana-ripe-20.a4d0ad33a7e6f037ac9276dc751ae62d56d3cc16e625837197ef49da426bc3c8.es.png new file mode 100644 index 00000000..4f2da8dc Binary files /dev/null and b/translated_images/banana-ripe-20.a4d0ad33a7e6f037ac9276dc751ae62d56d3cc16e625837197ef49da426bc3c8.es.png differ diff --git a/translated_images/banana-ripe-20.a4d0ad33a7e6f037ac9276dc751ae62d56d3cc16e625837197ef49da426bc3c8.hk.png b/translated_images/banana-ripe-20.a4d0ad33a7e6f037ac9276dc751ae62d56d3cc16e625837197ef49da426bc3c8.hk.png new file mode 100644 index 00000000..4f2da8dc Binary files /dev/null and b/translated_images/banana-ripe-20.a4d0ad33a7e6f037ac9276dc751ae62d56d3cc16e625837197ef49da426bc3c8.hk.png differ diff --git a/translated_images/banana-ripe-21.07e03d64f265d55dfe3b304df3e36f06140b87f80ae2cadd22a7736e2855eb8f.es.png b/translated_images/banana-ripe-21.07e03d64f265d55dfe3b304df3e36f06140b87f80ae2cadd22a7736e2855eb8f.es.png new file mode 100644 index 00000000..8ae3904c Binary files /dev/null and b/translated_images/banana-ripe-21.07e03d64f265d55dfe3b304df3e36f06140b87f80ae2cadd22a7736e2855eb8f.es.png differ diff --git a/translated_images/banana-ripe-21.07e03d64f265d55dfe3b304df3e36f06140b87f80ae2cadd22a7736e2855eb8f.hk.png b/translated_images/banana-ripe-21.07e03d64f265d55dfe3b304df3e36f06140b87f80ae2cadd22a7736e2855eb8f.hk.png new file mode 100644 index 00000000..8ae3904c Binary files /dev/null and b/translated_images/banana-ripe-21.07e03d64f265d55dfe3b304df3e36f06140b87f80ae2cadd22a7736e2855eb8f.hk.png differ diff --git a/translated_images/banana-ripe-22.a63c05aeb7f866fc64b6ac04e6fa68e1d1a22d729ad16d9fadf3357df97654a3.es.png b/translated_images/banana-ripe-22.a63c05aeb7f866fc64b6ac04e6fa68e1d1a22d729ad16d9fadf3357df97654a3.es.png new file mode 100644 index 00000000..ea5cbe30 Binary files /dev/null and b/translated_images/banana-ripe-22.a63c05aeb7f866fc64b6ac04e6fa68e1d1a22d729ad16d9fadf3357df97654a3.es.png differ diff --git a/translated_images/banana-ripe-22.a63c05aeb7f866fc64b6ac04e6fa68e1d1a22d729ad16d9fadf3357df97654a3.hk.png b/translated_images/banana-ripe-22.a63c05aeb7f866fc64b6ac04e6fa68e1d1a22d729ad16d9fadf3357df97654a3.hk.png new file mode 100644 index 00000000..ea5cbe30 Binary files /dev/null and b/translated_images/banana-ripe-22.a63c05aeb7f866fc64b6ac04e6fa68e1d1a22d729ad16d9fadf3357df97654a3.hk.png differ diff --git a/translated_images/banana-ripe-23.6f3364afcab19e571497cb5a3fa2b0c603a303beb31034cb82ae25635f4cc005.es.png b/translated_images/banana-ripe-23.6f3364afcab19e571497cb5a3fa2b0c603a303beb31034cb82ae25635f4cc005.es.png new file mode 100644 index 00000000..eab9fb03 Binary files /dev/null and b/translated_images/banana-ripe-23.6f3364afcab19e571497cb5a3fa2b0c603a303beb31034cb82ae25635f4cc005.es.png differ diff --git a/translated_images/banana-ripe-23.6f3364afcab19e571497cb5a3fa2b0c603a303beb31034cb82ae25635f4cc005.hk.png b/translated_images/banana-ripe-23.6f3364afcab19e571497cb5a3fa2b0c603a303beb31034cb82ae25635f4cc005.hk.png new file mode 100644 index 00000000..eab9fb03 Binary files /dev/null and b/translated_images/banana-ripe-23.6f3364afcab19e571497cb5a3fa2b0c603a303beb31034cb82ae25635f4cc005.hk.png differ diff --git a/translated_images/banana-ripe-24.ff2c02cc80a9c4301d1f851af0a96f414fcc844f912ea4bea902877c9d6978f6.es.png b/translated_images/banana-ripe-24.ff2c02cc80a9c4301d1f851af0a96f414fcc844f912ea4bea902877c9d6978f6.es.png new file mode 100644 index 00000000..c49c0459 Binary files /dev/null and b/translated_images/banana-ripe-24.ff2c02cc80a9c4301d1f851af0a96f414fcc844f912ea4bea902877c9d6978f6.es.png differ diff --git a/translated_images/banana-ripe-24.ff2c02cc80a9c4301d1f851af0a96f414fcc844f912ea4bea902877c9d6978f6.hk.png b/translated_images/banana-ripe-24.ff2c02cc80a9c4301d1f851af0a96f414fcc844f912ea4bea902877c9d6978f6.hk.png new file mode 100644 index 00000000..c49c0459 Binary files /dev/null and b/translated_images/banana-ripe-24.ff2c02cc80a9c4301d1f851af0a96f414fcc844f912ea4bea902877c9d6978f6.hk.png differ diff --git a/translated_images/banana-ripe-25.65ce63418cdc4de2d1d29d0fd35401a9f99e967938e01c3578f13a6b6812ae50.es.png b/translated_images/banana-ripe-25.65ce63418cdc4de2d1d29d0fd35401a9f99e967938e01c3578f13a6b6812ae50.es.png new file mode 100644 index 00000000..127b0257 Binary files /dev/null and b/translated_images/banana-ripe-25.65ce63418cdc4de2d1d29d0fd35401a9f99e967938e01c3578f13a6b6812ae50.es.png differ diff --git a/translated_images/banana-ripe-25.65ce63418cdc4de2d1d29d0fd35401a9f99e967938e01c3578f13a6b6812ae50.hk.png b/translated_images/banana-ripe-25.65ce63418cdc4de2d1d29d0fd35401a9f99e967938e01c3578f13a6b6812ae50.hk.png new file mode 100644 index 00000000..127b0257 Binary files /dev/null and b/translated_images/banana-ripe-25.65ce63418cdc4de2d1d29d0fd35401a9f99e967938e01c3578f13a6b6812ae50.hk.png differ diff --git a/translated_images/banana-ripe-3.4fae05a0a1d2b5f010998afee52fb77a113453a95331c76eb4b509c14d5cb5d7.es.png b/translated_images/banana-ripe-3.4fae05a0a1d2b5f010998afee52fb77a113453a95331c76eb4b509c14d5cb5d7.es.png new file mode 100644 index 00000000..0b528799 Binary files /dev/null and b/translated_images/banana-ripe-3.4fae05a0a1d2b5f010998afee52fb77a113453a95331c76eb4b509c14d5cb5d7.es.png differ diff --git a/translated_images/banana-ripe-3.4fae05a0a1d2b5f010998afee52fb77a113453a95331c76eb4b509c14d5cb5d7.hk.png b/translated_images/banana-ripe-3.4fae05a0a1d2b5f010998afee52fb77a113453a95331c76eb4b509c14d5cb5d7.hk.png new file mode 100644 index 00000000..0b528799 Binary files /dev/null and b/translated_images/banana-ripe-3.4fae05a0a1d2b5f010998afee52fb77a113453a95331c76eb4b509c14d5cb5d7.hk.png differ diff --git a/translated_images/banana-ripe-5.c762086879ccec4c5402fb5dd5387f4ee4c208de3ec13fd69a5461ef36cde34a.es.png b/translated_images/banana-ripe-5.c762086879ccec4c5402fb5dd5387f4ee4c208de3ec13fd69a5461ef36cde34a.es.png new file mode 100644 index 00000000..e5b04c65 Binary files /dev/null and b/translated_images/banana-ripe-5.c762086879ccec4c5402fb5dd5387f4ee4c208de3ec13fd69a5461ef36cde34a.es.png differ diff --git a/translated_images/banana-ripe-5.c762086879ccec4c5402fb5dd5387f4ee4c208de3ec13fd69a5461ef36cde34a.hk.png b/translated_images/banana-ripe-5.c762086879ccec4c5402fb5dd5387f4ee4c208de3ec13fd69a5461ef36cde34a.hk.png new file mode 100644 index 00000000..e5b04c65 Binary files /dev/null and b/translated_images/banana-ripe-5.c762086879ccec4c5402fb5dd5387f4ee4c208de3ec13fd69a5461ef36cde34a.hk.png differ diff --git a/translated_images/banana-ripe-6.5131bcbf492980cb737c3658b96f6ff3381ced4cd6505588b05bd95d82965c49.es.png b/translated_images/banana-ripe-6.5131bcbf492980cb737c3658b96f6ff3381ced4cd6505588b05bd95d82965c49.es.png new file mode 100644 index 00000000..46543926 Binary files /dev/null and b/translated_images/banana-ripe-6.5131bcbf492980cb737c3658b96f6ff3381ced4cd6505588b05bd95d82965c49.es.png differ diff --git a/translated_images/banana-ripe-6.5131bcbf492980cb737c3658b96f6ff3381ced4cd6505588b05bd95d82965c49.hk.png b/translated_images/banana-ripe-6.5131bcbf492980cb737c3658b96f6ff3381ced4cd6505588b05bd95d82965c49.hk.png new file mode 100644 index 00000000..46543926 Binary files /dev/null and b/translated_images/banana-ripe-6.5131bcbf492980cb737c3658b96f6ff3381ced4cd6505588b05bd95d82965c49.hk.png differ diff --git a/translated_images/banana-ripe-7.5fc18dfe7b7ae9dc5afe27cc6c0ce162c819b78b69b05f6f9c1636d5d1b82edc.es.png b/translated_images/banana-ripe-7.5fc18dfe7b7ae9dc5afe27cc6c0ce162c819b78b69b05f6f9c1636d5d1b82edc.es.png new file mode 100644 index 00000000..46e99668 Binary files /dev/null and b/translated_images/banana-ripe-7.5fc18dfe7b7ae9dc5afe27cc6c0ce162c819b78b69b05f6f9c1636d5d1b82edc.es.png differ diff --git a/translated_images/banana-ripe-7.5fc18dfe7b7ae9dc5afe27cc6c0ce162c819b78b69b05f6f9c1636d5d1b82edc.hk.png b/translated_images/banana-ripe-7.5fc18dfe7b7ae9dc5afe27cc6c0ce162c819b78b69b05f6f9c1636d5d1b82edc.hk.png new file mode 100644 index 00000000..46e99668 Binary files /dev/null and b/translated_images/banana-ripe-7.5fc18dfe7b7ae9dc5afe27cc6c0ce162c819b78b69b05f6f9c1636d5d1b82edc.hk.png differ diff --git a/translated_images/banana-ripe-8.dba1d33bd34d4830201c15a9c35c56fde4b1a45dc7dc5e3a7def9986bf1b6c28.es.png b/translated_images/banana-ripe-8.dba1d33bd34d4830201c15a9c35c56fde4b1a45dc7dc5e3a7def9986bf1b6c28.es.png new file mode 100644 index 00000000..c012d47d Binary files /dev/null and b/translated_images/banana-ripe-8.dba1d33bd34d4830201c15a9c35c56fde4b1a45dc7dc5e3a7def9986bf1b6c28.es.png differ diff --git a/translated_images/banana-ripe-8.dba1d33bd34d4830201c15a9c35c56fde4b1a45dc7dc5e3a7def9986bf1b6c28.hk.png b/translated_images/banana-ripe-8.dba1d33bd34d4830201c15a9c35c56fde4b1a45dc7dc5e3a7def9986bf1b6c28.hk.png new file mode 100644 index 00000000..c012d47d Binary files /dev/null and b/translated_images/banana-ripe-8.dba1d33bd34d4830201c15a9c35c56fde4b1a45dc7dc5e3a7def9986bf1b6c28.hk.png differ diff --git a/translated_images/banana-ripe-9.32f91462c8b0e2d3666f49a12afd84462212c5834835f988b3c37441c0493952.es.png b/translated_images/banana-ripe-9.32f91462c8b0e2d3666f49a12afd84462212c5834835f988b3c37441c0493952.es.png new file mode 100644 index 00000000..fa44061a Binary files /dev/null and b/translated_images/banana-ripe-9.32f91462c8b0e2d3666f49a12afd84462212c5834835f988b3c37441c0493952.es.png differ diff --git a/translated_images/banana-ripe-9.32f91462c8b0e2d3666f49a12afd84462212c5834835f988b3c37441c0493952.hk.png b/translated_images/banana-ripe-9.32f91462c8b0e2d3666f49a12afd84462212c5834835f988b3c37441c0493952.hk.png new file mode 100644 index 00000000..fa44061a Binary files /dev/null and b/translated_images/banana-ripe-9.32f91462c8b0e2d3666f49a12afd84462212c5834835f988b3c37441c0493952.hk.png differ diff --git a/translated_images/banana-training-images.530eb203346d73bc23b8b990fb4609470bf4ff7c942ccc13d4cfffeed9be1ad4.es.png b/translated_images/banana-training-images.530eb203346d73bc23b8b990fb4609470bf4ff7c942ccc13d4cfffeed9be1ad4.es.png new file mode 100644 index 00000000..e499b2fd Binary files /dev/null and b/translated_images/banana-training-images.530eb203346d73bc23b8b990fb4609470bf4ff7c942ccc13d4cfffeed9be1ad4.es.png differ diff --git a/translated_images/banana-training-images.530eb203346d73bc23b8b990fb4609470bf4ff7c942ccc13d4cfffeed9be1ad4.hk.png b/translated_images/banana-training-images.530eb203346d73bc23b8b990fb4609470bf4ff7c942ccc13d4cfffeed9be1ad4.hk.png new file mode 100644 index 00000000..e499b2fd Binary files /dev/null and b/translated_images/banana-training-images.530eb203346d73bc23b8b990fb4609470bf4ff7c942ccc13d4cfffeed9be1ad4.hk.png differ diff --git a/translated_images/banana-unripe-1.910c8606a300fa2014a0e0adb31348effd6e0fdd5760fdfe80b8e69533bac6f7.es.png b/translated_images/banana-unripe-1.910c8606a300fa2014a0e0adb31348effd6e0fdd5760fdfe80b8e69533bac6f7.es.png new file mode 100644 index 00000000..66e9927a Binary files /dev/null and b/translated_images/banana-unripe-1.910c8606a300fa2014a0e0adb31348effd6e0fdd5760fdfe80b8e69533bac6f7.es.png differ diff --git a/translated_images/banana-unripe-1.910c8606a300fa2014a0e0adb31348effd6e0fdd5760fdfe80b8e69533bac6f7.hk.png b/translated_images/banana-unripe-1.910c8606a300fa2014a0e0adb31348effd6e0fdd5760fdfe80b8e69533bac6f7.hk.png new file mode 100644 index 00000000..66e9927a Binary files /dev/null and b/translated_images/banana-unripe-1.910c8606a300fa2014a0e0adb31348effd6e0fdd5760fdfe80b8e69533bac6f7.hk.png differ diff --git a/translated_images/banana-unripe-1.b2c7051d9c8a4e617be0425bea42775d16f896f3a183344e9038da2d1fb81dea.es.png b/translated_images/banana-unripe-1.b2c7051d9c8a4e617be0425bea42775d16f896f3a183344e9038da2d1fb81dea.es.png new file mode 100644 index 00000000..e512cf63 Binary files /dev/null and b/translated_images/banana-unripe-1.b2c7051d9c8a4e617be0425bea42775d16f896f3a183344e9038da2d1fb81dea.es.png differ diff --git a/translated_images/banana-unripe-1.b2c7051d9c8a4e617be0425bea42775d16f896f3a183344e9038da2d1fb81dea.hk.png b/translated_images/banana-unripe-1.b2c7051d9c8a4e617be0425bea42775d16f896f3a183344e9038da2d1fb81dea.hk.png new file mode 100644 index 00000000..e512cf63 Binary files /dev/null and b/translated_images/banana-unripe-1.b2c7051d9c8a4e617be0425bea42775d16f896f3a183344e9038da2d1fb81dea.hk.png differ diff --git a/translated_images/banana-unripe-10.38dab0db918a24870e655b62e7f3af030eaebe5bcfb7cfebbfb010637b46ba44.es.png b/translated_images/banana-unripe-10.38dab0db918a24870e655b62e7f3af030eaebe5bcfb7cfebbfb010637b46ba44.es.png new file mode 100644 index 00000000..89e41b8a Binary files /dev/null and b/translated_images/banana-unripe-10.38dab0db918a24870e655b62e7f3af030eaebe5bcfb7cfebbfb010637b46ba44.es.png differ diff --git a/translated_images/banana-unripe-10.38dab0db918a24870e655b62e7f3af030eaebe5bcfb7cfebbfb010637b46ba44.hk.png b/translated_images/banana-unripe-10.38dab0db918a24870e655b62e7f3af030eaebe5bcfb7cfebbfb010637b46ba44.hk.png new file mode 100644 index 00000000..89e41b8a Binary files /dev/null and b/translated_images/banana-unripe-10.38dab0db918a24870e655b62e7f3af030eaebe5bcfb7cfebbfb010637b46ba44.hk.png differ diff --git a/translated_images/banana-unripe-11.ec8d0eefe63e10b953579d18d4fdd9d89cedc247749ec1d11fdbe49a43f1bc90.es.png b/translated_images/banana-unripe-11.ec8d0eefe63e10b953579d18d4fdd9d89cedc247749ec1d11fdbe49a43f1bc90.es.png new file mode 100644 index 00000000..257c3e55 Binary files /dev/null and b/translated_images/banana-unripe-11.ec8d0eefe63e10b953579d18d4fdd9d89cedc247749ec1d11fdbe49a43f1bc90.es.png differ diff --git a/translated_images/banana-unripe-11.ec8d0eefe63e10b953579d18d4fdd9d89cedc247749ec1d11fdbe49a43f1bc90.hk.png b/translated_images/banana-unripe-11.ec8d0eefe63e10b953579d18d4fdd9d89cedc247749ec1d11fdbe49a43f1bc90.hk.png new file mode 100644 index 00000000..257c3e55 Binary files /dev/null and b/translated_images/banana-unripe-11.ec8d0eefe63e10b953579d18d4fdd9d89cedc247749ec1d11fdbe49a43f1bc90.hk.png differ diff --git a/translated_images/banana-unripe-12.b95a088ccae935db01b47786dac829cb356feb5d4dbfcf8d91e000e9ed3be7a2.es.png b/translated_images/banana-unripe-12.b95a088ccae935db01b47786dac829cb356feb5d4dbfcf8d91e000e9ed3be7a2.es.png new file mode 100644 index 00000000..85a581ed Binary files /dev/null and b/translated_images/banana-unripe-12.b95a088ccae935db01b47786dac829cb356feb5d4dbfcf8d91e000e9ed3be7a2.es.png differ diff --git a/translated_images/banana-unripe-12.b95a088ccae935db01b47786dac829cb356feb5d4dbfcf8d91e000e9ed3be7a2.hk.png b/translated_images/banana-unripe-12.b95a088ccae935db01b47786dac829cb356feb5d4dbfcf8d91e000e9ed3be7a2.hk.png new file mode 100644 index 00000000..85a581ed Binary files /dev/null and b/translated_images/banana-unripe-12.b95a088ccae935db01b47786dac829cb356feb5d4dbfcf8d91e000e9ed3be7a2.hk.png differ diff --git a/translated_images/banana-unripe-13.37e5a7cac5aa0920343a6dd17dc720499d9f9b7c990cf4bc002f681216a545b7.es.png b/translated_images/banana-unripe-13.37e5a7cac5aa0920343a6dd17dc720499d9f9b7c990cf4bc002f681216a545b7.es.png new file mode 100644 index 00000000..c07f67c3 Binary files /dev/null and b/translated_images/banana-unripe-13.37e5a7cac5aa0920343a6dd17dc720499d9f9b7c990cf4bc002f681216a545b7.es.png differ diff --git a/translated_images/banana-unripe-13.37e5a7cac5aa0920343a6dd17dc720499d9f9b7c990cf4bc002f681216a545b7.hk.png b/translated_images/banana-unripe-13.37e5a7cac5aa0920343a6dd17dc720499d9f9b7c990cf4bc002f681216a545b7.hk.png new file mode 100644 index 00000000..c07f67c3 Binary files /dev/null and b/translated_images/banana-unripe-13.37e5a7cac5aa0920343a6dd17dc720499d9f9b7c990cf4bc002f681216a545b7.hk.png differ diff --git a/translated_images/banana-unripe-14.d19ddd6bbf63a2591db0d88a6c81e17d2186dee04b9bb4ff60031009fc0cce0a.es.png b/translated_images/banana-unripe-14.d19ddd6bbf63a2591db0d88a6c81e17d2186dee04b9bb4ff60031009fc0cce0a.es.png new file mode 100644 index 00000000..c598913b Binary files /dev/null and b/translated_images/banana-unripe-14.d19ddd6bbf63a2591db0d88a6c81e17d2186dee04b9bb4ff60031009fc0cce0a.es.png differ diff --git a/translated_images/banana-unripe-14.d19ddd6bbf63a2591db0d88a6c81e17d2186dee04b9bb4ff60031009fc0cce0a.hk.png b/translated_images/banana-unripe-14.d19ddd6bbf63a2591db0d88a6c81e17d2186dee04b9bb4ff60031009fc0cce0a.hk.png new file mode 100644 index 00000000..c598913b Binary files /dev/null and b/translated_images/banana-unripe-14.d19ddd6bbf63a2591db0d88a6c81e17d2186dee04b9bb4ff60031009fc0cce0a.hk.png differ diff --git a/translated_images/banana-unripe-15.274e48544326077a58c0e00e04e98c7abe04bc473caaab64fe3154c551d8a0a8.es.png b/translated_images/banana-unripe-15.274e48544326077a58c0e00e04e98c7abe04bc473caaab64fe3154c551d8a0a8.es.png new file mode 100644 index 00000000..a630a6f3 Binary files /dev/null and b/translated_images/banana-unripe-15.274e48544326077a58c0e00e04e98c7abe04bc473caaab64fe3154c551d8a0a8.es.png differ diff --git a/translated_images/banana-unripe-15.274e48544326077a58c0e00e04e98c7abe04bc473caaab64fe3154c551d8a0a8.hk.png b/translated_images/banana-unripe-15.274e48544326077a58c0e00e04e98c7abe04bc473caaab64fe3154c551d8a0a8.hk.png new file mode 100644 index 00000000..a630a6f3 Binary files /dev/null and b/translated_images/banana-unripe-15.274e48544326077a58c0e00e04e98c7abe04bc473caaab64fe3154c551d8a0a8.hk.png differ diff --git a/translated_images/banana-unripe-16.bd058f64bd7ec014d10bdeb9da39568aeb5871908b5c2a6376a5f97d3101c273.es.png b/translated_images/banana-unripe-16.bd058f64bd7ec014d10bdeb9da39568aeb5871908b5c2a6376a5f97d3101c273.es.png new file mode 100644 index 00000000..f63ad48d Binary files /dev/null and b/translated_images/banana-unripe-16.bd058f64bd7ec014d10bdeb9da39568aeb5871908b5c2a6376a5f97d3101c273.es.png differ diff --git a/translated_images/banana-unripe-16.bd058f64bd7ec014d10bdeb9da39568aeb5871908b5c2a6376a5f97d3101c273.hk.png b/translated_images/banana-unripe-16.bd058f64bd7ec014d10bdeb9da39568aeb5871908b5c2a6376a5f97d3101c273.hk.png new file mode 100644 index 00000000..f63ad48d Binary files /dev/null and b/translated_images/banana-unripe-16.bd058f64bd7ec014d10bdeb9da39568aeb5871908b5c2a6376a5f97d3101c273.hk.png differ diff --git a/translated_images/banana-unripe-17.408382d679bfa079fbe89e269fbc05a2602d2f980834601380633a5471c72396.es.png b/translated_images/banana-unripe-17.408382d679bfa079fbe89e269fbc05a2602d2f980834601380633a5471c72396.es.png new file mode 100644 index 00000000..73c0aea6 Binary files /dev/null and b/translated_images/banana-unripe-17.408382d679bfa079fbe89e269fbc05a2602d2f980834601380633a5471c72396.es.png differ diff --git a/translated_images/banana-unripe-17.408382d679bfa079fbe89e269fbc05a2602d2f980834601380633a5471c72396.hk.png b/translated_images/banana-unripe-17.408382d679bfa079fbe89e269fbc05a2602d2f980834601380633a5471c72396.hk.png new file mode 100644 index 00000000..73c0aea6 Binary files /dev/null and b/translated_images/banana-unripe-17.408382d679bfa079fbe89e269fbc05a2602d2f980834601380633a5471c72396.hk.png differ diff --git a/translated_images/banana-unripe-18.39c0eb79d7b3b9baf71858801fb8cb8b01e395289bab8c7091a57a97d1dfa075.es.png b/translated_images/banana-unripe-18.39c0eb79d7b3b9baf71858801fb8cb8b01e395289bab8c7091a57a97d1dfa075.es.png new file mode 100644 index 00000000..0768efbc Binary files /dev/null and b/translated_images/banana-unripe-18.39c0eb79d7b3b9baf71858801fb8cb8b01e395289bab8c7091a57a97d1dfa075.es.png differ diff --git a/translated_images/banana-unripe-18.39c0eb79d7b3b9baf71858801fb8cb8b01e395289bab8c7091a57a97d1dfa075.hk.png b/translated_images/banana-unripe-18.39c0eb79d7b3b9baf71858801fb8cb8b01e395289bab8c7091a57a97d1dfa075.hk.png new file mode 100644 index 00000000..0768efbc Binary files /dev/null and b/translated_images/banana-unripe-18.39c0eb79d7b3b9baf71858801fb8cb8b01e395289bab8c7091a57a97d1dfa075.hk.png differ diff --git a/translated_images/banana-unripe-19.e61e6d7efaf2d8c81a25acbff9c40f018b78c3c240c8e384d54da374eda70f9b.es.png b/translated_images/banana-unripe-19.e61e6d7efaf2d8c81a25acbff9c40f018b78c3c240c8e384d54da374eda70f9b.es.png new file mode 100644 index 00000000..a6c3afe8 Binary files /dev/null and b/translated_images/banana-unripe-19.e61e6d7efaf2d8c81a25acbff9c40f018b78c3c240c8e384d54da374eda70f9b.es.png differ diff --git a/translated_images/banana-unripe-19.e61e6d7efaf2d8c81a25acbff9c40f018b78c3c240c8e384d54da374eda70f9b.hk.png b/translated_images/banana-unripe-19.e61e6d7efaf2d8c81a25acbff9c40f018b78c3c240c8e384d54da374eda70f9b.hk.png new file mode 100644 index 00000000..a6c3afe8 Binary files /dev/null and b/translated_images/banana-unripe-19.e61e6d7efaf2d8c81a25acbff9c40f018b78c3c240c8e384d54da374eda70f9b.hk.png differ diff --git a/translated_images/banana-unripe-2.43a73b544521afc7efd54de90fd585f314844de67b16509fff2ab80c05eec7bd.es.png b/translated_images/banana-unripe-2.43a73b544521afc7efd54de90fd585f314844de67b16509fff2ab80c05eec7bd.es.png new file mode 100644 index 00000000..eed10ecb Binary files /dev/null and b/translated_images/banana-unripe-2.43a73b544521afc7efd54de90fd585f314844de67b16509fff2ab80c05eec7bd.es.png differ diff --git a/translated_images/banana-unripe-2.43a73b544521afc7efd54de90fd585f314844de67b16509fff2ab80c05eec7bd.hk.png b/translated_images/banana-unripe-2.43a73b544521afc7efd54de90fd585f314844de67b16509fff2ab80c05eec7bd.hk.png new file mode 100644 index 00000000..eed10ecb Binary files /dev/null and b/translated_images/banana-unripe-2.43a73b544521afc7efd54de90fd585f314844de67b16509fff2ab80c05eec7bd.hk.png differ diff --git a/translated_images/banana-unripe-2.9591d1a6aa27deebbaec0955b227bbae20d6bfae43f29d832bd412bbafa45bfd.es.png b/translated_images/banana-unripe-2.9591d1a6aa27deebbaec0955b227bbae20d6bfae43f29d832bd412bbafa45bfd.es.png new file mode 100644 index 00000000..4c086050 Binary files /dev/null and b/translated_images/banana-unripe-2.9591d1a6aa27deebbaec0955b227bbae20d6bfae43f29d832bd412bbafa45bfd.es.png differ diff --git a/translated_images/banana-unripe-2.9591d1a6aa27deebbaec0955b227bbae20d6bfae43f29d832bd412bbafa45bfd.hk.png b/translated_images/banana-unripe-2.9591d1a6aa27deebbaec0955b227bbae20d6bfae43f29d832bd412bbafa45bfd.hk.png new file mode 100644 index 00000000..4c086050 Binary files /dev/null and b/translated_images/banana-unripe-2.9591d1a6aa27deebbaec0955b227bbae20d6bfae43f29d832bd412bbafa45bfd.hk.png differ diff --git a/translated_images/banana-unripe-20.85b7a74eaab5634e769fe2fec57405201513094c400f71e16d75cd79bde092ab.es.png b/translated_images/banana-unripe-20.85b7a74eaab5634e769fe2fec57405201513094c400f71e16d75cd79bde092ab.es.png new file mode 100644 index 00000000..9f641588 Binary files /dev/null and b/translated_images/banana-unripe-20.85b7a74eaab5634e769fe2fec57405201513094c400f71e16d75cd79bde092ab.es.png differ diff --git a/translated_images/banana-unripe-20.85b7a74eaab5634e769fe2fec57405201513094c400f71e16d75cd79bde092ab.hk.png b/translated_images/banana-unripe-20.85b7a74eaab5634e769fe2fec57405201513094c400f71e16d75cd79bde092ab.hk.png new file mode 100644 index 00000000..9f641588 Binary files /dev/null and b/translated_images/banana-unripe-20.85b7a74eaab5634e769fe2fec57405201513094c400f71e16d75cd79bde092ab.hk.png differ diff --git a/translated_images/banana-unripe-21.ccc1333439b344bc502fbfa9b60e5e9013a4d57ba539ba87000ccd69dc0675e2.es.png b/translated_images/banana-unripe-21.ccc1333439b344bc502fbfa9b60e5e9013a4d57ba539ba87000ccd69dc0675e2.es.png new file mode 100644 index 00000000..9404843f Binary files /dev/null and b/translated_images/banana-unripe-21.ccc1333439b344bc502fbfa9b60e5e9013a4d57ba539ba87000ccd69dc0675e2.es.png differ diff --git a/translated_images/banana-unripe-21.ccc1333439b344bc502fbfa9b60e5e9013a4d57ba539ba87000ccd69dc0675e2.hk.png b/translated_images/banana-unripe-21.ccc1333439b344bc502fbfa9b60e5e9013a4d57ba539ba87000ccd69dc0675e2.hk.png new file mode 100644 index 00000000..9404843f Binary files /dev/null and b/translated_images/banana-unripe-21.ccc1333439b344bc502fbfa9b60e5e9013a4d57ba539ba87000ccd69dc0675e2.hk.png differ diff --git a/translated_images/banana-unripe-22.27dff4b438163080fcace0af6f24b8c9866b76a15269844e9ed1b722ae2220e7.es.png b/translated_images/banana-unripe-22.27dff4b438163080fcace0af6f24b8c9866b76a15269844e9ed1b722ae2220e7.es.png new file mode 100644 index 00000000..9636ac68 Binary files /dev/null and b/translated_images/banana-unripe-22.27dff4b438163080fcace0af6f24b8c9866b76a15269844e9ed1b722ae2220e7.es.png differ diff --git a/translated_images/banana-unripe-22.27dff4b438163080fcace0af6f24b8c9866b76a15269844e9ed1b722ae2220e7.hk.png b/translated_images/banana-unripe-22.27dff4b438163080fcace0af6f24b8c9866b76a15269844e9ed1b722ae2220e7.hk.png new file mode 100644 index 00000000..9636ac68 Binary files /dev/null and b/translated_images/banana-unripe-22.27dff4b438163080fcace0af6f24b8c9866b76a15269844e9ed1b722ae2220e7.hk.png differ diff --git a/translated_images/banana-unripe-23.c4c9067f23370e90c5156d7659a0d17590d952e2defd6550aeded84e847c1e4b.es.png b/translated_images/banana-unripe-23.c4c9067f23370e90c5156d7659a0d17590d952e2defd6550aeded84e847c1e4b.es.png new file mode 100644 index 00000000..38a2b35d Binary files /dev/null and b/translated_images/banana-unripe-23.c4c9067f23370e90c5156d7659a0d17590d952e2defd6550aeded84e847c1e4b.es.png differ diff --git a/translated_images/banana-unripe-23.c4c9067f23370e90c5156d7659a0d17590d952e2defd6550aeded84e847c1e4b.hk.png b/translated_images/banana-unripe-23.c4c9067f23370e90c5156d7659a0d17590d952e2defd6550aeded84e847c1e4b.hk.png new file mode 100644 index 00000000..38a2b35d Binary files /dev/null and b/translated_images/banana-unripe-23.c4c9067f23370e90c5156d7659a0d17590d952e2defd6550aeded84e847c1e4b.hk.png differ diff --git a/translated_images/banana-unripe-24.6f0b781c309da62f71147fcc87699967bef10c57a794029ede2eb0d1d88e4b73.es.png b/translated_images/banana-unripe-24.6f0b781c309da62f71147fcc87699967bef10c57a794029ede2eb0d1d88e4b73.es.png new file mode 100644 index 00000000..cd09e177 Binary files /dev/null and b/translated_images/banana-unripe-24.6f0b781c309da62f71147fcc87699967bef10c57a794029ede2eb0d1d88e4b73.es.png differ diff --git a/translated_images/banana-unripe-24.6f0b781c309da62f71147fcc87699967bef10c57a794029ede2eb0d1d88e4b73.hk.png b/translated_images/banana-unripe-24.6f0b781c309da62f71147fcc87699967bef10c57a794029ede2eb0d1d88e4b73.hk.png new file mode 100644 index 00000000..cd09e177 Binary files /dev/null and b/translated_images/banana-unripe-24.6f0b781c309da62f71147fcc87699967bef10c57a794029ede2eb0d1d88e4b73.hk.png differ diff --git a/translated_images/banana-unripe-25.21d553d84880ac4ff73128909d01c79c4544424d218f740482da46bdae46f74b.es.png b/translated_images/banana-unripe-25.21d553d84880ac4ff73128909d01c79c4544424d218f740482da46bdae46f74b.es.png new file mode 100644 index 00000000..4cc4f4bc Binary files /dev/null and b/translated_images/banana-unripe-25.21d553d84880ac4ff73128909d01c79c4544424d218f740482da46bdae46f74b.es.png differ diff --git a/translated_images/banana-unripe-25.21d553d84880ac4ff73128909d01c79c4544424d218f740482da46bdae46f74b.hk.png b/translated_images/banana-unripe-25.21d553d84880ac4ff73128909d01c79c4544424d218f740482da46bdae46f74b.hk.png new file mode 100644 index 00000000..4cc4f4bc Binary files /dev/null and b/translated_images/banana-unripe-25.21d553d84880ac4ff73128909d01c79c4544424d218f740482da46bdae46f74b.hk.png differ diff --git a/translated_images/banana-unripe-26.823c48b61feb1d5c319e9cf54f5e7c2bb43f91e781bf42d57f386d0dabf3fd12.es.png b/translated_images/banana-unripe-26.823c48b61feb1d5c319e9cf54f5e7c2bb43f91e781bf42d57f386d0dabf3fd12.es.png new file mode 100644 index 00000000..33e03220 Binary files /dev/null and b/translated_images/banana-unripe-26.823c48b61feb1d5c319e9cf54f5e7c2bb43f91e781bf42d57f386d0dabf3fd12.es.png differ diff --git a/translated_images/banana-unripe-26.823c48b61feb1d5c319e9cf54f5e7c2bb43f91e781bf42d57f386d0dabf3fd12.hk.png b/translated_images/banana-unripe-26.823c48b61feb1d5c319e9cf54f5e7c2bb43f91e781bf42d57f386d0dabf3fd12.hk.png new file mode 100644 index 00000000..33e03220 Binary files /dev/null and b/translated_images/banana-unripe-26.823c48b61feb1d5c319e9cf54f5e7c2bb43f91e781bf42d57f386d0dabf3fd12.hk.png differ diff --git a/translated_images/banana-unripe-27.f98fd272deeb02d9b6771340fe6da2de82db652ade770d9eca14ba6be2d0ad17.es.png b/translated_images/banana-unripe-27.f98fd272deeb02d9b6771340fe6da2de82db652ade770d9eca14ba6be2d0ad17.es.png new file mode 100644 index 00000000..489d49e3 Binary files /dev/null and b/translated_images/banana-unripe-27.f98fd272deeb02d9b6771340fe6da2de82db652ade770d9eca14ba6be2d0ad17.es.png differ diff --git a/translated_images/banana-unripe-27.f98fd272deeb02d9b6771340fe6da2de82db652ade770d9eca14ba6be2d0ad17.hk.png b/translated_images/banana-unripe-27.f98fd272deeb02d9b6771340fe6da2de82db652ade770d9eca14ba6be2d0ad17.hk.png new file mode 100644 index 00000000..489d49e3 Binary files /dev/null and b/translated_images/banana-unripe-27.f98fd272deeb02d9b6771340fe6da2de82db652ade770d9eca14ba6be2d0ad17.hk.png differ diff --git a/translated_images/banana-unripe-28.5331ba409ce41c07caa09d72d6ad7375b5a5b3d7609fcabdaa82d9799439fd21.es.png b/translated_images/banana-unripe-28.5331ba409ce41c07caa09d72d6ad7375b5a5b3d7609fcabdaa82d9799439fd21.es.png new file mode 100644 index 00000000..80b39b63 Binary files /dev/null and b/translated_images/banana-unripe-28.5331ba409ce41c07caa09d72d6ad7375b5a5b3d7609fcabdaa82d9799439fd21.es.png differ diff --git a/translated_images/banana-unripe-28.5331ba409ce41c07caa09d72d6ad7375b5a5b3d7609fcabdaa82d9799439fd21.hk.png b/translated_images/banana-unripe-28.5331ba409ce41c07caa09d72d6ad7375b5a5b3d7609fcabdaa82d9799439fd21.hk.png new file mode 100644 index 00000000..80b39b63 Binary files /dev/null and b/translated_images/banana-unripe-28.5331ba409ce41c07caa09d72d6ad7375b5a5b3d7609fcabdaa82d9799439fd21.hk.png differ diff --git a/translated_images/banana-unripe-29.84e126f389bf627ed464abdf8127f3a58e8b0131b5b1b9ee038de51703c31657.es.png b/translated_images/banana-unripe-29.84e126f389bf627ed464abdf8127f3a58e8b0131b5b1b9ee038de51703c31657.es.png new file mode 100644 index 00000000..2404a4ce Binary files /dev/null and b/translated_images/banana-unripe-29.84e126f389bf627ed464abdf8127f3a58e8b0131b5b1b9ee038de51703c31657.es.png differ diff --git a/translated_images/banana-unripe-29.84e126f389bf627ed464abdf8127f3a58e8b0131b5b1b9ee038de51703c31657.hk.png b/translated_images/banana-unripe-29.84e126f389bf627ed464abdf8127f3a58e8b0131b5b1b9ee038de51703c31657.hk.png new file mode 100644 index 00000000..2404a4ce Binary files /dev/null and b/translated_images/banana-unripe-29.84e126f389bf627ed464abdf8127f3a58e8b0131b5b1b9ee038de51703c31657.hk.png differ diff --git a/translated_images/banana-unripe-3.896df8fb2c3b8f51f71b212645fc5314b591a033938208000839642858ddcabd.es.png b/translated_images/banana-unripe-3.896df8fb2c3b8f51f71b212645fc5314b591a033938208000839642858ddcabd.es.png new file mode 100644 index 00000000..f884cc81 Binary files /dev/null and b/translated_images/banana-unripe-3.896df8fb2c3b8f51f71b212645fc5314b591a033938208000839642858ddcabd.es.png differ diff --git a/translated_images/banana-unripe-3.896df8fb2c3b8f51f71b212645fc5314b591a033938208000839642858ddcabd.hk.png b/translated_images/banana-unripe-3.896df8fb2c3b8f51f71b212645fc5314b591a033938208000839642858ddcabd.hk.png new file mode 100644 index 00000000..f884cc81 Binary files /dev/null and b/translated_images/banana-unripe-3.896df8fb2c3b8f51f71b212645fc5314b591a033938208000839642858ddcabd.hk.png differ diff --git a/translated_images/banana-unripe-4.483e740d6fd7b5a671cb49ad1b0f2c35f1637f86ccb9746bb4cc3b59ab752bf7.es.png b/translated_images/banana-unripe-4.483e740d6fd7b5a671cb49ad1b0f2c35f1637f86ccb9746bb4cc3b59ab752bf7.es.png new file mode 100644 index 00000000..9f649bd1 Binary files /dev/null and b/translated_images/banana-unripe-4.483e740d6fd7b5a671cb49ad1b0f2c35f1637f86ccb9746bb4cc3b59ab752bf7.es.png differ diff --git a/translated_images/banana-unripe-4.483e740d6fd7b5a671cb49ad1b0f2c35f1637f86ccb9746bb4cc3b59ab752bf7.hk.png b/translated_images/banana-unripe-4.483e740d6fd7b5a671cb49ad1b0f2c35f1637f86ccb9746bb4cc3b59ab752bf7.hk.png new file mode 100644 index 00000000..9f649bd1 Binary files /dev/null and b/translated_images/banana-unripe-4.483e740d6fd7b5a671cb49ad1b0f2c35f1637f86ccb9746bb4cc3b59ab752bf7.hk.png differ diff --git a/translated_images/banana-unripe-5.e9923cf1ffcfc1c93e8c2aeb184bd071566742b738b671ab9cedcd5708239a58.es.png b/translated_images/banana-unripe-5.e9923cf1ffcfc1c93e8c2aeb184bd071566742b738b671ab9cedcd5708239a58.es.png new file mode 100644 index 00000000..03e1fa8c Binary files /dev/null and b/translated_images/banana-unripe-5.e9923cf1ffcfc1c93e8c2aeb184bd071566742b738b671ab9cedcd5708239a58.es.png differ diff --git a/translated_images/banana-unripe-5.e9923cf1ffcfc1c93e8c2aeb184bd071566742b738b671ab9cedcd5708239a58.hk.png b/translated_images/banana-unripe-5.e9923cf1ffcfc1c93e8c2aeb184bd071566742b738b671ab9cedcd5708239a58.hk.png new file mode 100644 index 00000000..03e1fa8c Binary files /dev/null and b/translated_images/banana-unripe-5.e9923cf1ffcfc1c93e8c2aeb184bd071566742b738b671ab9cedcd5708239a58.hk.png differ diff --git a/translated_images/banana-unripe-6.e3a73307558caecc9aac5ae80bbe37ca38f105e2bd7311afab61ee1014fc6c0e.es.png b/translated_images/banana-unripe-6.e3a73307558caecc9aac5ae80bbe37ca38f105e2bd7311afab61ee1014fc6c0e.es.png new file mode 100644 index 00000000..983f836f Binary files /dev/null and b/translated_images/banana-unripe-6.e3a73307558caecc9aac5ae80bbe37ca38f105e2bd7311afab61ee1014fc6c0e.es.png differ diff --git a/translated_images/banana-unripe-6.e3a73307558caecc9aac5ae80bbe37ca38f105e2bd7311afab61ee1014fc6c0e.hk.png b/translated_images/banana-unripe-6.e3a73307558caecc9aac5ae80bbe37ca38f105e2bd7311afab61ee1014fc6c0e.hk.png new file mode 100644 index 00000000..983f836f Binary files /dev/null and b/translated_images/banana-unripe-6.e3a73307558caecc9aac5ae80bbe37ca38f105e2bd7311afab61ee1014fc6c0e.hk.png differ diff --git a/translated_images/banana-unripe-7.634ca89acc17d68f8423b1a13f1bec6bdbd5135f0149c6cfaa53d7b7d5fa1c65.es.png b/translated_images/banana-unripe-7.634ca89acc17d68f8423b1a13f1bec6bdbd5135f0149c6cfaa53d7b7d5fa1c65.es.png new file mode 100644 index 00000000..2aede939 Binary files /dev/null and b/translated_images/banana-unripe-7.634ca89acc17d68f8423b1a13f1bec6bdbd5135f0149c6cfaa53d7b7d5fa1c65.es.png differ diff --git a/translated_images/banana-unripe-7.634ca89acc17d68f8423b1a13f1bec6bdbd5135f0149c6cfaa53d7b7d5fa1c65.hk.png b/translated_images/banana-unripe-7.634ca89acc17d68f8423b1a13f1bec6bdbd5135f0149c6cfaa53d7b7d5fa1c65.hk.png new file mode 100644 index 00000000..2aede939 Binary files /dev/null and b/translated_images/banana-unripe-7.634ca89acc17d68f8423b1a13f1bec6bdbd5135f0149c6cfaa53d7b7d5fa1c65.hk.png differ diff --git a/translated_images/banana-unripe-8.75720b4cdebac8c36964c86e051ea962ab02e530abec3f577bd77fdbc34d7f9d.es.png b/translated_images/banana-unripe-8.75720b4cdebac8c36964c86e051ea962ab02e530abec3f577bd77fdbc34d7f9d.es.png new file mode 100644 index 00000000..7bc7bab2 Binary files /dev/null and b/translated_images/banana-unripe-8.75720b4cdebac8c36964c86e051ea962ab02e530abec3f577bd77fdbc34d7f9d.es.png differ diff --git a/translated_images/banana-unripe-8.75720b4cdebac8c36964c86e051ea962ab02e530abec3f577bd77fdbc34d7f9d.hk.png b/translated_images/banana-unripe-8.75720b4cdebac8c36964c86e051ea962ab02e530abec3f577bd77fdbc34d7f9d.hk.png new file mode 100644 index 00000000..7bc7bab2 Binary files /dev/null and b/translated_images/banana-unripe-8.75720b4cdebac8c36964c86e051ea962ab02e530abec3f577bd77fdbc34d7f9d.hk.png differ diff --git a/translated_images/banana-unripe-9.e8076983351d2f54cfb246bc01090e7016b63fb8d81396822cbe5366c1b88b7f.es.png b/translated_images/banana-unripe-9.e8076983351d2f54cfb246bc01090e7016b63fb8d81396822cbe5366c1b88b7f.es.png new file mode 100644 index 00000000..4ffd862a Binary files /dev/null and b/translated_images/banana-unripe-9.e8076983351d2f54cfb246bc01090e7016b63fb8d81396822cbe5366c1b88b7f.es.png differ diff --git a/translated_images/banana-unripe-9.e8076983351d2f54cfb246bc01090e7016b63fb8d81396822cbe5366c1b88b7f.hk.png b/translated_images/banana-unripe-9.e8076983351d2f54cfb246bc01090e7016b63fb8d81396822cbe5366c1b88b7f.hk.png new file mode 100644 index 00000000..4ffd862a Binary files /dev/null and b/translated_images/banana-unripe-9.e8076983351d2f54cfb246bc01090e7016b63fb8d81396822cbe5366c1b88b7f.hk.png differ diff --git a/translated_images/banana-unripe-quick-test-prediction.dae9b5e1c4ef7c64886422438850ea14f0be6ac918c217ea3b255c685abfabe7.es.png b/translated_images/banana-unripe-quick-test-prediction.dae9b5e1c4ef7c64886422438850ea14f0be6ac918c217ea3b255c685abfabe7.es.png new file mode 100644 index 00000000..ef506579 Binary files /dev/null and b/translated_images/banana-unripe-quick-test-prediction.dae9b5e1c4ef7c64886422438850ea14f0be6ac918c217ea3b255c685abfabe7.es.png differ diff --git a/translated_images/banana-unripe-quick-test-prediction.dae9b5e1c4ef7c64886422438850ea14f0be6ac918c217ea3b255c685abfabe7.hk.png b/translated_images/banana-unripe-quick-test-prediction.dae9b5e1c4ef7c64886422438850ea14f0be6ac918c217ea3b255c685abfabe7.hk.png new file mode 100644 index 00000000..ef506579 Binary files /dev/null and b/translated_images/banana-unripe-quick-test-prediction.dae9b5e1c4ef7c64886422438850ea14f0be6ac918c217ea3b255c685abfabe7.hk.png differ diff --git a/translated_images/bananas-ripe-vs-unripe-predictions.8d0e2034014aa50ece4e4589e724b142da0681f35470fe3db3f7d51240f69c85.es.png b/translated_images/bananas-ripe-vs-unripe-predictions.8d0e2034014aa50ece4e4589e724b142da0681f35470fe3db3f7d51240f69c85.es.png new file mode 100644 index 00000000..ddf79213 Binary files /dev/null and b/translated_images/bananas-ripe-vs-unripe-predictions.8d0e2034014aa50ece4e4589e724b142da0681f35470fe3db3f7d51240f69c85.es.png differ diff --git a/translated_images/bananas-ripe-vs-unripe-predictions.8d0e2034014aa50ece4e4589e724b142da0681f35470fe3db3f7d51240f69c85.hk.png b/translated_images/bananas-ripe-vs-unripe-predictions.8d0e2034014aa50ece4e4589e724b142da0681f35470fe3db3f7d51240f69c85.hk.png new file mode 100644 index 00000000..ddf79213 Binary files /dev/null and b/translated_images/bananas-ripe-vs-unripe-predictions.8d0e2034014aa50ece4e4589e724b142da0681f35470fe3db3f7d51240f69c85.hk.png differ diff --git a/translated_images/basic-thermostat.a923217fd1f37e5a6f3390396a65c22a387419ea2dd17e518ec24315ba6ae9a8.es.png b/translated_images/basic-thermostat.a923217fd1f37e5a6f3390396a65c22a387419ea2dd17e518ec24315ba6ae9a8.es.png new file mode 100644 index 00000000..1796bcce Binary files /dev/null and b/translated_images/basic-thermostat.a923217fd1f37e5a6f3390396a65c22a387419ea2dd17e518ec24315ba6ae9a8.es.png differ diff --git a/translated_images/basic-thermostat.a923217fd1f37e5a6f3390396a65c22a387419ea2dd17e518ec24315ba6ae9a8.hk.png b/translated_images/basic-thermostat.a923217fd1f37e5a6f3390396a65c22a387419ea2dd17e518ec24315ba6ae9a8.hk.png new file mode 100644 index 00000000..1796bcce Binary files /dev/null and b/translated_images/basic-thermostat.a923217fd1f37e5a6f3390396a65c22a387419ea2dd17e518ec24315ba6ae9a8.hk.png differ diff --git a/translated_images/bing-translate.348aa796d6efe2a92f41ea74a5cf42bb4c63d6faaa08e7f46924e072a35daa48.es.png b/translated_images/bing-translate.348aa796d6efe2a92f41ea74a5cf42bb4c63d6faaa08e7f46924e072a35daa48.es.png new file mode 100644 index 00000000..ab763666 Binary files /dev/null and b/translated_images/bing-translate.348aa796d6efe2a92f41ea74a5cf42bb4c63d6faaa08e7f46924e072a35daa48.es.png differ diff --git a/translated_images/bing-translate.348aa796d6efe2a92f41ea74a5cf42bb4c63d6faaa08e7f46924e072a35daa48.hk.png b/translated_images/bing-translate.348aa796d6efe2a92f41ea74a5cf42bb4c63d6faaa08e7f46924e072a35daa48.hk.png new file mode 100644 index 00000000..ab763666 Binary files /dev/null and b/translated_images/bing-translate.348aa796d6efe2a92f41ea74a5cf42bb4c63d6faaa08e7f46924e072a35daa48.hk.png differ diff --git a/translated_images/bounding-box.1420a7ea0d3d15f71e1ffb5cf4b2271d184fac051f990abc541975168d163684.es.png b/translated_images/bounding-box.1420a7ea0d3d15f71e1ffb5cf4b2271d184fac051f990abc541975168d163684.es.png new file mode 100644 index 00000000..013f247d Binary files /dev/null and b/translated_images/bounding-box.1420a7ea0d3d15f71e1ffb5cf4b2271d184fac051f990abc541975168d163684.es.png differ diff --git a/translated_images/bounding-box.1420a7ea0d3d15f71e1ffb5cf4b2271d184fac051f990abc541975168d163684.hk.png b/translated_images/bounding-box.1420a7ea0d3d15f71e1ffb5cf4b2271d184fac051f990abc541975168d163684.hk.png new file mode 100644 index 00000000..013f247d Binary files /dev/null and b/translated_images/bounding-box.1420a7ea0d3d15f71e1ffb5cf4b2271d184fac051f990abc541975168d163684.hk.png differ diff --git a/translated_images/bricked-car.dc38f8efadc6c59d76211f981a521efb300939283dee468f79503aae3ec67615.es.png b/translated_images/bricked-car.dc38f8efadc6c59d76211f981a521efb300939283dee468f79503aae3ec67615.es.png new file mode 100644 index 00000000..fd1b7753 Binary files /dev/null and b/translated_images/bricked-car.dc38f8efadc6c59d76211f981a521efb300939283dee468f79503aae3ec67615.es.png differ diff --git a/translated_images/bricked-car.dc38f8efadc6c59d76211f981a521efb300939283dee468f79503aae3ec67615.hk.png b/translated_images/bricked-car.dc38f8efadc6c59d76211f981a521efb300939283dee468f79503aae3ec67615.hk.png new file mode 100644 index 00000000..fd1b7753 Binary files /dev/null and b/translated_images/bricked-car.dc38f8efadc6c59d76211f981a521efb300939283dee468f79503aae3ec67615.hk.png differ diff --git a/translated_images/button-with-digital.3749edea8eb885af0303f7ea29e2389d704661c0ca3225b08ff0cbc22f332059.es.png b/translated_images/button-with-digital.3749edea8eb885af0303f7ea29e2389d704661c0ca3225b08ff0cbc22f332059.es.png new file mode 100644 index 00000000..55154b84 Binary files /dev/null and b/translated_images/button-with-digital.3749edea8eb885af0303f7ea29e2389d704661c0ca3225b08ff0cbc22f332059.es.png differ diff --git a/translated_images/button-with-digital.3749edea8eb885af0303f7ea29e2389d704661c0ca3225b08ff0cbc22f332059.hk.png b/translated_images/button-with-digital.3749edea8eb885af0303f7ea29e2389d704661c0ca3225b08ff0cbc22f332059.hk.png new file mode 100644 index 00000000..55154b84 Binary files /dev/null and b/translated_images/button-with-digital.3749edea8eb885af0303f7ea29e2389d704661c0ca3225b08ff0cbc22f332059.hk.png differ diff --git a/translated_images/button.eadb560b77ac45e56f523d9d8876e40444f63b419e33eb820082d461fa79490b.es.png b/translated_images/button.eadb560b77ac45e56f523d9d8876e40444f63b419e33eb820082d461fa79490b.es.png new file mode 100644 index 00000000..306d6f14 Binary files /dev/null and b/translated_images/button.eadb560b77ac45e56f523d9d8876e40444f63b419e33eb820082d461fa79490b.es.png differ diff --git a/translated_images/button.eadb560b77ac45e56f523d9d8876e40444f63b419e33eb820082d461fa79490b.hk.png b/translated_images/button.eadb560b77ac45e56f523d9d8876e40444f63b419e33eb820082d461fa79490b.hk.png new file mode 100644 index 00000000..306d6f14 Binary files /dev/null and b/translated_images/button.eadb560b77ac45e56f523d9d8876e40444f63b419e33eb820082d461fa79490b.hk.png differ diff --git a/translated_images/chart-soil-moisture-relay.fbb391236d34a64d0abf1df396e9197e0a24df14150620b9cc820a64a55c9326.es.png b/translated_images/chart-soil-moisture-relay.fbb391236d34a64d0abf1df396e9197e0a24df14150620b9cc820a64a55c9326.es.png new file mode 100644 index 00000000..dfb03646 Binary files /dev/null and b/translated_images/chart-soil-moisture-relay.fbb391236d34a64d0abf1df396e9197e0a24df14150620b9cc820a64a55c9326.es.png differ diff --git a/translated_images/chart-soil-moisture-relay.fbb391236d34a64d0abf1df396e9197e0a24df14150620b9cc820a64a55c9326.hk.png b/translated_images/chart-soil-moisture-relay.fbb391236d34a64d0abf1df396e9197e0a24df14150620b9cc820a64a55c9326.hk.png new file mode 100644 index 00000000..dfb03646 Binary files /dev/null and b/translated_images/chart-soil-moisture-relay.fbb391236d34a64d0abf1df396e9197e0a24df14150620b9cc820a64a55c9326.hk.png differ diff --git a/translated_images/chart-soil-moisture.fd6d9d0cdc0b5f75e78038ecb8945dfc84b38851359de99d84b16e3336d6d7c2.es.png b/translated_images/chart-soil-moisture.fd6d9d0cdc0b5f75e78038ecb8945dfc84b38851359de99d84b16e3336d6d7c2.es.png new file mode 100644 index 00000000..05208120 Binary files /dev/null and b/translated_images/chart-soil-moisture.fd6d9d0cdc0b5f75e78038ecb8945dfc84b38851359de99d84b16e3336d6d7c2.es.png differ diff --git a/translated_images/chart-soil-moisture.fd6d9d0cdc0b5f75e78038ecb8945dfc84b38851359de99d84b16e3336d6d7c2.hk.png b/translated_images/chart-soil-moisture.fd6d9d0cdc0b5f75e78038ecb8945dfc84b38851359de99d84b16e3336d6d7c2.hk.png new file mode 100644 index 00000000..05208120 Binary files /dev/null and b/translated_images/chart-soil-moisture.fd6d9d0cdc0b5f75e78038ecb8945dfc84b38851359de99d84b16e3336d6d7c2.hk.png differ diff --git a/translated_images/child-watering-garden.9a5d3f1bfe6d0d8d488291e8189899b2c59f82abaa487f18d404217a25e671e7.es.jpg b/translated_images/child-watering-garden.9a5d3f1bfe6d0d8d488291e8189899b2c59f82abaa487f18d404217a25e671e7.es.jpg new file mode 100644 index 00000000..e78b8c6c Binary files /dev/null and b/translated_images/child-watering-garden.9a5d3f1bfe6d0d8d488291e8189899b2c59f82abaa487f18d404217a25e671e7.es.jpg differ diff --git a/translated_images/child-watering-garden.9a5d3f1bfe6d0d8d488291e8189899b2c59f82abaa487f18d404217a25e671e7.hk.jpg b/translated_images/child-watering-garden.9a5d3f1bfe6d0d8d488291e8189899b2c59f82abaa487f18d404217a25e671e7.hk.jpg new file mode 100644 index 00000000..e78b8c6c Binary files /dev/null and b/translated_images/child-watering-garden.9a5d3f1bfe6d0d8d488291e8189899b2c59f82abaa487f18d404217a25e671e7.hk.jpg differ diff --git a/translated_images/cloud-with-edge.1e26462c62c126fe150bd15a5714ddf0be599f09bacbad08b85be02b76ea1ae1.es.png b/translated_images/cloud-with-edge.1e26462c62c126fe150bd15a5714ddf0be599f09bacbad08b85be02b76ea1ae1.es.png new file mode 100644 index 00000000..0b221a3f Binary files /dev/null and b/translated_images/cloud-with-edge.1e26462c62c126fe150bd15a5714ddf0be599f09bacbad08b85be02b76ea1ae1.es.png differ diff --git a/translated_images/cloud-with-edge.1e26462c62c126fe150bd15a5714ddf0be599f09bacbad08b85be02b76ea1ae1.hk.png b/translated_images/cloud-with-edge.1e26462c62c126fe150bd15a5714ddf0be599f09bacbad08b85be02b76ea1ae1.hk.png new file mode 100644 index 00000000..0b221a3f Binary files /dev/null and b/translated_images/cloud-with-edge.1e26462c62c126fe150bd15a5714ddf0be599f09bacbad08b85be02b76ea1ae1.hk.png differ diff --git a/translated_images/cloud-without-edge.b4da641f6022c95ed6b91fde8b5323abd2f94e0d52073ad54172ae8f5dac90e9.es.png b/translated_images/cloud-without-edge.b4da641f6022c95ed6b91fde8b5323abd2f94e0d52073ad54172ae8f5dac90e9.es.png new file mode 100644 index 00000000..576d3f84 Binary files /dev/null and b/translated_images/cloud-without-edge.b4da641f6022c95ed6b91fde8b5323abd2f94e0d52073ad54172ae8f5dac90e9.es.png differ diff --git a/translated_images/cloud-without-edge.b4da641f6022c95ed6b91fde8b5323abd2f94e0d52073ad54172ae8f5dac90e9.hk.png b/translated_images/cloud-without-edge.b4da641f6022c95ed6b91fde8b5323abd2f94e0d52073ad54172ae8f5dac90e9.hk.png new file mode 100644 index 00000000..576d3f84 Binary files /dev/null and b/translated_images/cloud-without-edge.b4da641f6022c95ed6b91fde8b5323abd2f94e0d52073ad54172ae8f5dac90e9.hk.png differ diff --git a/translated_images/cmos-sensor.75f9cd74decb137149a4c9ea825251a4549497d67c0ae2776159e6102bb53aa9.es.png b/translated_images/cmos-sensor.75f9cd74decb137149a4c9ea825251a4549497d67c0ae2776159e6102bb53aa9.es.png new file mode 100644 index 00000000..297ccc5e Binary files /dev/null and b/translated_images/cmos-sensor.75f9cd74decb137149a4c9ea825251a4549497d67c0ae2776159e6102bb53aa9.es.png differ diff --git a/translated_images/cmos-sensor.75f9cd74decb137149a4c9ea825251a4549497d67c0ae2776159e6102bb53aa9.hk.png b/translated_images/cmos-sensor.75f9cd74decb137149a4c9ea825251a4549497d67c0ae2776159e6102bb53aa9.hk.png new file mode 100644 index 00000000..297ccc5e Binary files /dev/null and b/translated_images/cmos-sensor.75f9cd74decb137149a4c9ea825251a4549497d67c0ae2776159e6102bb53aa9.hk.png differ diff --git a/translated_images/commands.d6c06bbbb3a02cce95f2831a1c331daf6dedd4e470c4aa2b0ae54f332016e504.es.png b/translated_images/commands.d6c06bbbb3a02cce95f2831a1c331daf6dedd4e470c4aa2b0ae54f332016e504.es.png new file mode 100644 index 00000000..89bd1ba6 Binary files /dev/null and b/translated_images/commands.d6c06bbbb3a02cce95f2831a1c331daf6dedd4e470c4aa2b0ae54f332016e504.es.png differ diff --git a/translated_images/commands.d6c06bbbb3a02cce95f2831a1c331daf6dedd4e470c4aa2b0ae54f332016e504.hk.png b/translated_images/commands.d6c06bbbb3a02cce95f2831a1c331daf6dedd4e470c4aa2b0ae54f332016e504.hk.png new file mode 100644 index 00000000..89bd1ba6 Binary files /dev/null and b/translated_images/commands.d6c06bbbb3a02cce95f2831a1c331daf6dedd4e470c4aa2b0ae54f332016e504.hk.png differ diff --git a/translated_images/condenser-mic.6f6ed5b76ca19e0ec3fd0c544601542d4479a6cb7565db336de49fbbf69f623e.es.jpg b/translated_images/condenser-mic.6f6ed5b76ca19e0ec3fd0c544601542d4479a6cb7565db336de49fbbf69f623e.es.jpg new file mode 100644 index 00000000..383794f2 Binary files /dev/null and b/translated_images/condenser-mic.6f6ed5b76ca19e0ec3fd0c544601542d4479a6cb7565db336de49fbbf69f623e.es.jpg differ diff --git a/translated_images/condenser-mic.6f6ed5b76ca19e0ec3fd0c544601542d4479a6cb7565db336de49fbbf69f623e.hk.jpg b/translated_images/condenser-mic.6f6ed5b76ca19e0ec3fd0c544601542d4479a6cb7565db336de49fbbf69f623e.hk.jpg new file mode 100644 index 00000000..383794f2 Binary files /dev/null and b/translated_images/condenser-mic.6f6ed5b76ca19e0ec3fd0c544601542d4479a6cb7565db336de49fbbf69f623e.hk.jpg differ diff --git a/translated_images/consumer-groups.a3262e26fc27ba2092863678ad57af15c7223416e388a23f330c058cf4358630.es.png b/translated_images/consumer-groups.a3262e26fc27ba2092863678ad57af15c7223416e388a23f330c058cf4358630.es.png new file mode 100644 index 00000000..f28538e1 Binary files /dev/null and b/translated_images/consumer-groups.a3262e26fc27ba2092863678ad57af15c7223416e388a23f330c058cf4358630.es.png differ diff --git a/translated_images/consumer-groups.a3262e26fc27ba2092863678ad57af15c7223416e388a23f330c058cf4358630.hk.png b/translated_images/consumer-groups.a3262e26fc27ba2092863678ad57af15c7223416e388a23f330c058cf4358630.hk.png new file mode 100644 index 00000000..f28538e1 Binary files /dev/null and b/translated_images/consumer-groups.a3262e26fc27ba2092863678ad57af15c7223416e388a23f330c058cf4358630.hk.png differ diff --git a/translated_images/container-edge-flow.c246050dd60ceefdb6ace026a4ce5c6aa4112bb5898ae23fbb2ab4be29ae3e1b.es.png b/translated_images/container-edge-flow.c246050dd60ceefdb6ace026a4ce5c6aa4112bb5898ae23fbb2ab4be29ae3e1b.es.png new file mode 100644 index 00000000..39431760 Binary files /dev/null and b/translated_images/container-edge-flow.c246050dd60ceefdb6ace026a4ce5c6aa4112bb5898ae23fbb2ab4be29ae3e1b.es.png differ diff --git a/translated_images/container-edge-flow.c246050dd60ceefdb6ace026a4ce5c6aa4112bb5898ae23fbb2ab4be29ae3e1b.hk.png b/translated_images/container-edge-flow.c246050dd60ceefdb6ace026a4ce5c6aa4112bb5898ae23fbb2ab4be29ae3e1b.hk.png new file mode 100644 index 00000000..39431760 Binary files /dev/null and b/translated_images/container-edge-flow.c246050dd60ceefdb6ace026a4ce5c6aa4112bb5898ae23fbb2ab4be29ae3e1b.hk.png differ diff --git a/translated_images/container-web-browser.4ee81dd4f0d8838ce622b2a0d600b6a4322b5d4fe43159facd87b7b34f84d66a.es.png b/translated_images/container-web-browser.4ee81dd4f0d8838ce622b2a0d600b6a4322b5d4fe43159facd87b7b34f84d66a.es.png new file mode 100644 index 00000000..46a26d45 Binary files /dev/null and b/translated_images/container-web-browser.4ee81dd4f0d8838ce622b2a0d600b6a4322b5d4fe43159facd87b7b34f84d66a.es.png differ diff --git a/translated_images/container-web-browser.4ee81dd4f0d8838ce622b2a0d600b6a4322b5d4fe43159facd87b7b34f84d66a.hk.png b/translated_images/container-web-browser.4ee81dd4f0d8838ce622b2a0d600b6a4322b5d4fe43159facd87b7b34f84d66a.hk.png new file mode 100644 index 00000000..46a26d45 Binary files /dev/null and b/translated_images/container-web-browser.4ee81dd4f0d8838ce622b2a0d600b6a4322b5d4fe43159facd87b7b34f84d66a.hk.png differ diff --git a/translated_images/counterfit-camera-options.eb3bd5150a8e7dffbf24bc5bcaba0cf2cdef95fbe6bbe393695d173817d6b8df.es.png b/translated_images/counterfit-camera-options.eb3bd5150a8e7dffbf24bc5bcaba0cf2cdef95fbe6bbe393695d173817d6b8df.es.png new file mode 100644 index 00000000..6f70239b Binary files /dev/null and b/translated_images/counterfit-camera-options.eb3bd5150a8e7dffbf24bc5bcaba0cf2cdef95fbe6bbe393695d173817d6b8df.es.png differ diff --git a/translated_images/counterfit-camera-options.eb3bd5150a8e7dffbf24bc5bcaba0cf2cdef95fbe6bbe393695d173817d6b8df.hk.png b/translated_images/counterfit-camera-options.eb3bd5150a8e7dffbf24bc5bcaba0cf2cdef95fbe6bbe393695d173817d6b8df.hk.png new file mode 100644 index 00000000..6f70239b Binary files /dev/null and b/translated_images/counterfit-camera-options.eb3bd5150a8e7dffbf24bc5bcaba0cf2cdef95fbe6bbe393695d173817d6b8df.hk.png differ diff --git a/translated_images/counterfit-camera.001ec52194c8ee5d3f617173da2c79e1df903d10882adc625cbfc493525125d4.es.png b/translated_images/counterfit-camera.001ec52194c8ee5d3f617173da2c79e1df903d10882adc625cbfc493525125d4.es.png new file mode 100644 index 00000000..c5cd51da Binary files /dev/null and b/translated_images/counterfit-camera.001ec52194c8ee5d3f617173da2c79e1df903d10882adc625cbfc493525125d4.es.png differ diff --git a/translated_images/counterfit-camera.001ec52194c8ee5d3f617173da2c79e1df903d10882adc625cbfc493525125d4.hk.png b/translated_images/counterfit-camera.001ec52194c8ee5d3f617173da2c79e1df903d10882adc625cbfc493525125d4.hk.png new file mode 100644 index 00000000..c5cd51da Binary files /dev/null and b/translated_images/counterfit-camera.001ec52194c8ee5d3f617173da2c79e1df903d10882adc625cbfc493525125d4.hk.png differ diff --git a/translated_images/counterfit-connected.ed30b46d8f79b0921f3fc70be10366e596a89dca3f80c2224a9d9fc98fccf884.es.png b/translated_images/counterfit-connected.ed30b46d8f79b0921f3fc70be10366e596a89dca3f80c2224a9d9fc98fccf884.es.png new file mode 100644 index 00000000..0328b3ea Binary files /dev/null and b/translated_images/counterfit-connected.ed30b46d8f79b0921f3fc70be10366e596a89dca3f80c2224a9d9fc98fccf884.es.png differ diff --git a/translated_images/counterfit-connected.ed30b46d8f79b0921f3fc70be10366e596a89dca3f80c2224a9d9fc98fccf884.hk.png b/translated_images/counterfit-connected.ed30b46d8f79b0921f3fc70be10366e596a89dca3f80c2224a9d9fc98fccf884.hk.png new file mode 100644 index 00000000..0328b3ea Binary files /dev/null and b/translated_images/counterfit-connected.ed30b46d8f79b0921f3fc70be10366e596a89dca3f80c2224a9d9fc98fccf884.hk.png differ diff --git a/translated_images/counterfit-create-camera.a5de97f59c0bd3cbe0416d7e89a3cfe86d19fbae05c641c53a91286412af0a34.es.png b/translated_images/counterfit-create-camera.a5de97f59c0bd3cbe0416d7e89a3cfe86d19fbae05c641c53a91286412af0a34.es.png new file mode 100644 index 00000000..b3d0d223 Binary files /dev/null and b/translated_images/counterfit-create-camera.a5de97f59c0bd3cbe0416d7e89a3cfe86d19fbae05c641c53a91286412af0a34.es.png differ diff --git a/translated_images/counterfit-create-camera.a5de97f59c0bd3cbe0416d7e89a3cfe86d19fbae05c641c53a91286412af0a34.hk.png b/translated_images/counterfit-create-camera.a5de97f59c0bd3cbe0416d7e89a3cfe86d19fbae05c641c53a91286412af0a34.hk.png new file mode 100644 index 00000000..b3d0d223 Binary files /dev/null and b/translated_images/counterfit-create-camera.a5de97f59c0bd3cbe0416d7e89a3cfe86d19fbae05c641c53a91286412af0a34.hk.png differ diff --git a/translated_images/counterfit-create-distance-sensor.967c9fb98f27888d95920c9784d004c972490eb71f70397fe13bd70a79a879a3.es.png b/translated_images/counterfit-create-distance-sensor.967c9fb98f27888d95920c9784d004c972490eb71f70397fe13bd70a79a879a3.es.png new file mode 100644 index 00000000..0729dbce Binary files /dev/null and b/translated_images/counterfit-create-distance-sensor.967c9fb98f27888d95920c9784d004c972490eb71f70397fe13bd70a79a879a3.es.png differ diff --git a/translated_images/counterfit-create-distance-sensor.967c9fb98f27888d95920c9784d004c972490eb71f70397fe13bd70a79a879a3.hk.png b/translated_images/counterfit-create-distance-sensor.967c9fb98f27888d95920c9784d004c972490eb71f70397fe13bd70a79a879a3.hk.png new file mode 100644 index 00000000..0729dbce Binary files /dev/null and b/translated_images/counterfit-create-distance-sensor.967c9fb98f27888d95920c9784d004c972490eb71f70397fe13bd70a79a879a3.hk.png differ diff --git a/translated_images/counterfit-create-gps-sensor.6385dc9357d85ad1d47b4abb2525e7651fd498917d25eefc5a72feab09eedc70.es.png b/translated_images/counterfit-create-gps-sensor.6385dc9357d85ad1d47b4abb2525e7651fd498917d25eefc5a72feab09eedc70.es.png new file mode 100644 index 00000000..2e3adef5 Binary files /dev/null and b/translated_images/counterfit-create-gps-sensor.6385dc9357d85ad1d47b4abb2525e7651fd498917d25eefc5a72feab09eedc70.es.png differ diff --git a/translated_images/counterfit-create-gps-sensor.6385dc9357d85ad1d47b4abb2525e7651fd498917d25eefc5a72feab09eedc70.hk.png b/translated_images/counterfit-create-gps-sensor.6385dc9357d85ad1d47b4abb2525e7651fd498917d25eefc5a72feab09eedc70.hk.png new file mode 100644 index 00000000..2e3adef5 Binary files /dev/null and b/translated_images/counterfit-create-gps-sensor.6385dc9357d85ad1d47b4abb2525e7651fd498917d25eefc5a72feab09eedc70.hk.png differ diff --git a/translated_images/counterfit-create-humidity-sensor.2750e27b6f30e09cf4e22101defd5252710717620816ab41ba688f91f757c49a.es.png b/translated_images/counterfit-create-humidity-sensor.2750e27b6f30e09cf4e22101defd5252710717620816ab41ba688f91f757c49a.es.png new file mode 100644 index 00000000..4e9aa9b4 Binary files /dev/null and b/translated_images/counterfit-create-humidity-sensor.2750e27b6f30e09cf4e22101defd5252710717620816ab41ba688f91f757c49a.es.png differ diff --git a/translated_images/counterfit-create-humidity-sensor.2750e27b6f30e09cf4e22101defd5252710717620816ab41ba688f91f757c49a.hk.png b/translated_images/counterfit-create-humidity-sensor.2750e27b6f30e09cf4e22101defd5252710717620816ab41ba688f91f757c49a.hk.png new file mode 100644 index 00000000..4e9aa9b4 Binary files /dev/null and b/translated_images/counterfit-create-humidity-sensor.2750e27b6f30e09cf4e22101defd5252710717620816ab41ba688f91f757c49a.hk.png differ diff --git a/translated_images/counterfit-create-led.ba9db1c9b8c622a635d6dfae5cdc4e70c2b250635bd4f0601c6cf0bd22b7ba46.es.png b/translated_images/counterfit-create-led.ba9db1c9b8c622a635d6dfae5cdc4e70c2b250635bd4f0601c6cf0bd22b7ba46.es.png new file mode 100644 index 00000000..766527c0 Binary files /dev/null and b/translated_images/counterfit-create-led.ba9db1c9b8c622a635d6dfae5cdc4e70c2b250635bd4f0601c6cf0bd22b7ba46.es.png differ diff --git a/translated_images/counterfit-create-led.ba9db1c9b8c622a635d6dfae5cdc4e70c2b250635bd4f0601c6cf0bd22b7ba46.hk.png b/translated_images/counterfit-create-led.ba9db1c9b8c622a635d6dfae5cdc4e70c2b250635bd4f0601c6cf0bd22b7ba46.hk.png new file mode 100644 index 00000000..766527c0 Binary files /dev/null and b/translated_images/counterfit-create-led.ba9db1c9b8c622a635d6dfae5cdc4e70c2b250635bd4f0601c6cf0bd22b7ba46.hk.png differ diff --git a/translated_images/counterfit-create-light-sensor.9f36a5e0d4458d8d554d54b34d2c806d56093d6e49fddcda2d20f6fef7f5cce1.es.png b/translated_images/counterfit-create-light-sensor.9f36a5e0d4458d8d554d54b34d2c806d56093d6e49fddcda2d20f6fef7f5cce1.es.png new file mode 100644 index 00000000..f34ad7c6 Binary files /dev/null and b/translated_images/counterfit-create-light-sensor.9f36a5e0d4458d8d554d54b34d2c806d56093d6e49fddcda2d20f6fef7f5cce1.es.png differ diff --git a/translated_images/counterfit-create-light-sensor.9f36a5e0d4458d8d554d54b34d2c806d56093d6e49fddcda2d20f6fef7f5cce1.hk.png b/translated_images/counterfit-create-light-sensor.9f36a5e0d4458d8d554d54b34d2c806d56093d6e49fddcda2d20f6fef7f5cce1.hk.png new file mode 100644 index 00000000..f34ad7c6 Binary files /dev/null and b/translated_images/counterfit-create-light-sensor.9f36a5e0d4458d8d554d54b34d2c806d56093d6e49fddcda2d20f6fef7f5cce1.hk.png differ diff --git a/translated_images/counterfit-create-relay.fa7c40fd0f2f6afc33b35ea94fcb235085be4861e14e3fe6b9b7bcfc82d1c888.es.png b/translated_images/counterfit-create-relay.fa7c40fd0f2f6afc33b35ea94fcb235085be4861e14e3fe6b9b7bcfc82d1c888.es.png new file mode 100644 index 00000000..403bb436 Binary files /dev/null and b/translated_images/counterfit-create-relay.fa7c40fd0f2f6afc33b35ea94fcb235085be4861e14e3fe6b9b7bcfc82d1c888.es.png differ diff --git a/translated_images/counterfit-create-relay.fa7c40fd0f2f6afc33b35ea94fcb235085be4861e14e3fe6b9b7bcfc82d1c888.hk.png b/translated_images/counterfit-create-relay.fa7c40fd0f2f6afc33b35ea94fcb235085be4861e14e3fe6b9b7bcfc82d1c888.hk.png new file mode 100644 index 00000000..403bb436 Binary files /dev/null and b/translated_images/counterfit-create-relay.fa7c40fd0f2f6afc33b35ea94fcb235085be4861e14e3fe6b9b7bcfc82d1c888.hk.png differ diff --git a/translated_images/counterfit-create-soil-moisture-sensor.35266135a5e0ae68b29a684d7db0d2933a8098b2307d197f7c71577b724603aa.es.png b/translated_images/counterfit-create-soil-moisture-sensor.35266135a5e0ae68b29a684d7db0d2933a8098b2307d197f7c71577b724603aa.es.png new file mode 100644 index 00000000..07398a97 Binary files /dev/null and b/translated_images/counterfit-create-soil-moisture-sensor.35266135a5e0ae68b29a684d7db0d2933a8098b2307d197f7c71577b724603aa.es.png differ diff --git a/translated_images/counterfit-create-soil-moisture-sensor.35266135a5e0ae68b29a684d7db0d2933a8098b2307d197f7c71577b724603aa.hk.png b/translated_images/counterfit-create-soil-moisture-sensor.35266135a5e0ae68b29a684d7db0d2933a8098b2307d197f7c71577b724603aa.hk.png new file mode 100644 index 00000000..07398a97 Binary files /dev/null and b/translated_images/counterfit-create-soil-moisture-sensor.35266135a5e0ae68b29a684d7db0d2933a8098b2307d197f7c71577b724603aa.hk.png differ diff --git a/translated_images/counterfit-create-temperature-sensor.199350ed34f7343d79dccbe95eaf6c11d2121f03d1c35ab9613b330c23f39b29.es.png b/translated_images/counterfit-create-temperature-sensor.199350ed34f7343d79dccbe95eaf6c11d2121f03d1c35ab9613b330c23f39b29.es.png new file mode 100644 index 00000000..83d0a29e Binary files /dev/null and b/translated_images/counterfit-create-temperature-sensor.199350ed34f7343d79dccbe95eaf6c11d2121f03d1c35ab9613b330c23f39b29.es.png differ diff --git a/translated_images/counterfit-create-temperature-sensor.199350ed34f7343d79dccbe95eaf6c11d2121f03d1c35ab9613b330c23f39b29.hk.png b/translated_images/counterfit-create-temperature-sensor.199350ed34f7343d79dccbe95eaf6c11d2121f03d1c35ab9613b330c23f39b29.hk.png new file mode 100644 index 00000000..83d0a29e Binary files /dev/null and b/translated_images/counterfit-create-temperature-sensor.199350ed34f7343d79dccbe95eaf6c11d2121f03d1c35ab9613b330c23f39b29.hk.png differ diff --git a/translated_images/counterfit-distance-sensor.079eefeeea0b68afc36431ce8fcbe2f09a7e4916ed1cd5cb30e696db53bc18fa.es.png b/translated_images/counterfit-distance-sensor.079eefeeea0b68afc36431ce8fcbe2f09a7e4916ed1cd5cb30e696db53bc18fa.es.png new file mode 100644 index 00000000..cdd566f5 Binary files /dev/null and b/translated_images/counterfit-distance-sensor.079eefeeea0b68afc36431ce8fcbe2f09a7e4916ed1cd5cb30e696db53bc18fa.es.png differ diff --git a/translated_images/counterfit-distance-sensor.079eefeeea0b68afc36431ce8fcbe2f09a7e4916ed1cd5cb30e696db53bc18fa.hk.png b/translated_images/counterfit-distance-sensor.079eefeeea0b68afc36431ce8fcbe2f09a7e4916ed1cd5cb30e696db53bc18fa.hk.png new file mode 100644 index 00000000..cdd566f5 Binary files /dev/null and b/translated_images/counterfit-distance-sensor.079eefeeea0b68afc36431ce8fcbe2f09a7e4916ed1cd5cb30e696db53bc18fa.hk.png differ diff --git a/translated_images/counterfit-first-run.433326358b669b31d0e99c3513cb01bfbb13724d162c99cdcc8f51ecf5f9c779.es.png b/translated_images/counterfit-first-run.433326358b669b31d0e99c3513cb01bfbb13724d162c99cdcc8f51ecf5f9c779.es.png new file mode 100644 index 00000000..50caa7a8 Binary files /dev/null and b/translated_images/counterfit-first-run.433326358b669b31d0e99c3513cb01bfbb13724d162c99cdcc8f51ecf5f9c779.es.png differ diff --git a/translated_images/counterfit-first-run.433326358b669b31d0e99c3513cb01bfbb13724d162c99cdcc8f51ecf5f9c779.hk.png b/translated_images/counterfit-first-run.433326358b669b31d0e99c3513cb01bfbb13724d162c99cdcc8f51ecf5f9c779.hk.png new file mode 100644 index 00000000..50caa7a8 Binary files /dev/null and b/translated_images/counterfit-first-run.433326358b669b31d0e99c3513cb01bfbb13724d162c99cdcc8f51ecf5f9c779.hk.png differ diff --git a/translated_images/counterfit-gps-sensor-gpxfile.8310b063ce8a425ccc8ebeec8306aeac5e8e55207f007d52c6e1194432a70cd9.es.png b/translated_images/counterfit-gps-sensor-gpxfile.8310b063ce8a425ccc8ebeec8306aeac5e8e55207f007d52c6e1194432a70cd9.es.png new file mode 100644 index 00000000..e68c1881 Binary files /dev/null and b/translated_images/counterfit-gps-sensor-gpxfile.8310b063ce8a425ccc8ebeec8306aeac5e8e55207f007d52c6e1194432a70cd9.es.png differ diff --git a/translated_images/counterfit-gps-sensor-gpxfile.8310b063ce8a425ccc8ebeec8306aeac5e8e55207f007d52c6e1194432a70cd9.hk.png b/translated_images/counterfit-gps-sensor-gpxfile.8310b063ce8a425ccc8ebeec8306aeac5e8e55207f007d52c6e1194432a70cd9.hk.png new file mode 100644 index 00000000..e68c1881 Binary files /dev/null and b/translated_images/counterfit-gps-sensor-gpxfile.8310b063ce8a425ccc8ebeec8306aeac5e8e55207f007d52c6e1194432a70cd9.hk.png differ diff --git a/translated_images/counterfit-gps-sensor-latlon.008c867d75464fbe7f84107cc57040df565ac07cb57d2f21db37d087d470197d.es.png b/translated_images/counterfit-gps-sensor-latlon.008c867d75464fbe7f84107cc57040df565ac07cb57d2f21db37d087d470197d.es.png new file mode 100644 index 00000000..357708db Binary files /dev/null and b/translated_images/counterfit-gps-sensor-latlon.008c867d75464fbe7f84107cc57040df565ac07cb57d2f21db37d087d470197d.es.png differ diff --git a/translated_images/counterfit-gps-sensor-latlon.008c867d75464fbe7f84107cc57040df565ac07cb57d2f21db37d087d470197d.hk.png b/translated_images/counterfit-gps-sensor-latlon.008c867d75464fbe7f84107cc57040df565ac07cb57d2f21db37d087d470197d.hk.png new file mode 100644 index 00000000..357708db Binary files /dev/null and b/translated_images/counterfit-gps-sensor-latlon.008c867d75464fbe7f84107cc57040df565ac07cb57d2f21db37d087d470197d.hk.png differ diff --git a/translated_images/counterfit-gps-sensor-nmea.c62eea442171e17e19528b051b104cfcecdc9cd18db7bc72920f29821ae63f73.es.png b/translated_images/counterfit-gps-sensor-nmea.c62eea442171e17e19528b051b104cfcecdc9cd18db7bc72920f29821ae63f73.es.png new file mode 100644 index 00000000..ff2cb168 Binary files /dev/null and b/translated_images/counterfit-gps-sensor-nmea.c62eea442171e17e19528b051b104cfcecdc9cd18db7bc72920f29821ae63f73.es.png differ diff --git a/translated_images/counterfit-gps-sensor-nmea.c62eea442171e17e19528b051b104cfcecdc9cd18db7bc72920f29821ae63f73.hk.png b/translated_images/counterfit-gps-sensor-nmea.c62eea442171e17e19528b051b104cfcecdc9cd18db7bc72920f29821ae63f73.hk.png new file mode 100644 index 00000000..ff2cb168 Binary files /dev/null and b/translated_images/counterfit-gps-sensor-nmea.c62eea442171e17e19528b051b104cfcecdc9cd18db7bc72920f29821ae63f73.hk.png differ diff --git a/translated_images/counterfit-gps-sensor.3fbb15af0a5367566f2f11324ef5a6f30861cdf2b497071a5e002b7aa473550e.es.png b/translated_images/counterfit-gps-sensor.3fbb15af0a5367566f2f11324ef5a6f30861cdf2b497071a5e002b7aa473550e.es.png new file mode 100644 index 00000000..4dd28830 Binary files /dev/null and b/translated_images/counterfit-gps-sensor.3fbb15af0a5367566f2f11324ef5a6f30861cdf2b497071a5e002b7aa473550e.es.png differ diff --git a/translated_images/counterfit-gps-sensor.3fbb15af0a5367566f2f11324ef5a6f30861cdf2b497071a5e002b7aa473550e.hk.png b/translated_images/counterfit-gps-sensor.3fbb15af0a5367566f2f11324ef5a6f30861cdf2b497071a5e002b7aa473550e.hk.png new file mode 100644 index 00000000..4dd28830 Binary files /dev/null and b/translated_images/counterfit-gps-sensor.3fbb15af0a5367566f2f11324ef5a6f30861cdf2b497071a5e002b7aa473550e.hk.png differ diff --git a/translated_images/counterfit-humidity-sensor.7b12f7f339e430cb26c8211d2dba4ef75261b353a01da0932698b5bebd693f27.es.png b/translated_images/counterfit-humidity-sensor.7b12f7f339e430cb26c8211d2dba4ef75261b353a01da0932698b5bebd693f27.es.png new file mode 100644 index 00000000..36a0bed7 Binary files /dev/null and b/translated_images/counterfit-humidity-sensor.7b12f7f339e430cb26c8211d2dba4ef75261b353a01da0932698b5bebd693f27.es.png differ diff --git a/translated_images/counterfit-humidity-sensor.7b12f7f339e430cb26c8211d2dba4ef75261b353a01da0932698b5bebd693f27.hk.png b/translated_images/counterfit-humidity-sensor.7b12f7f339e430cb26c8211d2dba4ef75261b353a01da0932698b5bebd693f27.hk.png new file mode 100644 index 00000000..36a0bed7 Binary files /dev/null and b/translated_images/counterfit-humidity-sensor.7b12f7f339e430cb26c8211d2dba4ef75261b353a01da0932698b5bebd693f27.hk.png differ diff --git a/translated_images/counterfit-led.c0ab02de6d256ad84d9bad4d67a7faa709f0ea83e410cfe9b5561ef0cef30b1c.es.png b/translated_images/counterfit-led.c0ab02de6d256ad84d9bad4d67a7faa709f0ea83e410cfe9b5561ef0cef30b1c.es.png new file mode 100644 index 00000000..43b82415 Binary files /dev/null and b/translated_images/counterfit-led.c0ab02de6d256ad84d9bad4d67a7faa709f0ea83e410cfe9b5561ef0cef30b1c.es.png differ diff --git a/translated_images/counterfit-led.c0ab02de6d256ad84d9bad4d67a7faa709f0ea83e410cfe9b5561ef0cef30b1c.hk.png b/translated_images/counterfit-led.c0ab02de6d256ad84d9bad4d67a7faa709f0ea83e410cfe9b5561ef0cef30b1c.hk.png new file mode 100644 index 00000000..43b82415 Binary files /dev/null and b/translated_images/counterfit-led.c0ab02de6d256ad84d9bad4d67a7faa709f0ea83e410cfe9b5561ef0cef30b1c.hk.png differ diff --git a/translated_images/counterfit-light-sensor.5d0f5584df56b90f6b2561910d9cb20dfbd73eeff2177c238d38f4de54aefae1.es.png b/translated_images/counterfit-light-sensor.5d0f5584df56b90f6b2561910d9cb20dfbd73eeff2177c238d38f4de54aefae1.es.png new file mode 100644 index 00000000..9f42e92d Binary files /dev/null and b/translated_images/counterfit-light-sensor.5d0f5584df56b90f6b2561910d9cb20dfbd73eeff2177c238d38f4de54aefae1.es.png differ diff --git a/translated_images/counterfit-light-sensor.5d0f5584df56b90f6b2561910d9cb20dfbd73eeff2177c238d38f4de54aefae1.hk.png b/translated_images/counterfit-light-sensor.5d0f5584df56b90f6b2561910d9cb20dfbd73eeff2177c238d38f4de54aefae1.hk.png new file mode 100644 index 00000000..9f42e92d Binary files /dev/null and b/translated_images/counterfit-light-sensor.5d0f5584df56b90f6b2561910d9cb20dfbd73eeff2177c238d38f4de54aefae1.hk.png differ diff --git a/translated_images/counterfit-relay.bbf74c1dbdc8b9acd983367fcbd06703a402aefef6af54ddb28e11307ba8a12c.es.png b/translated_images/counterfit-relay.bbf74c1dbdc8b9acd983367fcbd06703a402aefef6af54ddb28e11307ba8a12c.es.png new file mode 100644 index 00000000..91118b35 Binary files /dev/null and b/translated_images/counterfit-relay.bbf74c1dbdc8b9acd983367fcbd06703a402aefef6af54ddb28e11307ba8a12c.es.png differ diff --git a/translated_images/counterfit-relay.bbf74c1dbdc8b9acd983367fcbd06703a402aefef6af54ddb28e11307ba8a12c.hk.png b/translated_images/counterfit-relay.bbf74c1dbdc8b9acd983367fcbd06703a402aefef6af54ddb28e11307ba8a12c.hk.png new file mode 100644 index 00000000..91118b35 Binary files /dev/null and b/translated_images/counterfit-relay.bbf74c1dbdc8b9acd983367fcbd06703a402aefef6af54ddb28e11307ba8a12c.hk.png differ diff --git a/translated_images/counterfit-soil-moisture-sensor.81742b2de0e9de60a3b3b9a2ff8ecc686d428eb6d71820f27a693be26e5aceee.es.png b/translated_images/counterfit-soil-moisture-sensor.81742b2de0e9de60a3b3b9a2ff8ecc686d428eb6d71820f27a693be26e5aceee.es.png new file mode 100644 index 00000000..c1074a8e Binary files /dev/null and b/translated_images/counterfit-soil-moisture-sensor.81742b2de0e9de60a3b3b9a2ff8ecc686d428eb6d71820f27a693be26e5aceee.es.png differ diff --git a/translated_images/counterfit-soil-moisture-sensor.81742b2de0e9de60a3b3b9a2ff8ecc686d428eb6d71820f27a693be26e5aceee.hk.png b/translated_images/counterfit-soil-moisture-sensor.81742b2de0e9de60a3b3b9a2ff8ecc686d428eb6d71820f27a693be26e5aceee.hk.png new file mode 100644 index 00000000..c1074a8e Binary files /dev/null and b/translated_images/counterfit-soil-moisture-sensor.81742b2de0e9de60a3b3b9a2ff8ecc686d428eb6d71820f27a693be26e5aceee.hk.png differ diff --git a/translated_images/counterfit-temperature-sensor.f0560236c96a9016bafce7f6f792476fe3367bc6941a1f7d5811d144d4bcbfff.es.png b/translated_images/counterfit-temperature-sensor.f0560236c96a9016bafce7f6f792476fe3367bc6941a1f7d5811d144d4bcbfff.es.png new file mode 100644 index 00000000..a4cca4dc Binary files /dev/null and b/translated_images/counterfit-temperature-sensor.f0560236c96a9016bafce7f6f792476fe3367bc6941a1f7d5811d144d4bcbfff.es.png differ diff --git a/translated_images/counterfit-temperature-sensor.f0560236c96a9016bafce7f6f792476fe3367bc6941a1f7d5811d144d4bcbfff.hk.png b/translated_images/counterfit-temperature-sensor.f0560236c96a9016bafce7f6f792476fe3367bc6941a1f7d5811d144d4bcbfff.hk.png new file mode 100644 index 00000000..a4cca4dc Binary files /dev/null and b/translated_images/counterfit-temperature-sensor.f0560236c96a9016bafce7f6f792476fe3367bc6941a1f7d5811d144d4bcbfff.hk.png differ diff --git a/translated_images/custom-vision-banana-prediction.30cdff4e1d72db5d9a0be0193790a47c2b387da034e12dc1314dd57ca2131b59.es.png b/translated_images/custom-vision-banana-prediction.30cdff4e1d72db5d9a0be0193790a47c2b387da034e12dc1314dd57ca2131b59.es.png new file mode 100644 index 00000000..1dd02459 Binary files /dev/null and b/translated_images/custom-vision-banana-prediction.30cdff4e1d72db5d9a0be0193790a47c2b387da034e12dc1314dd57ca2131b59.es.png differ diff --git a/translated_images/custom-vision-banana-prediction.30cdff4e1d72db5d9a0be0193790a47c2b387da034e12dc1314dd57ca2131b59.hk.png b/translated_images/custom-vision-banana-prediction.30cdff4e1d72db5d9a0be0193790a47c2b387da034e12dc1314dd57ca2131b59.hk.png new file mode 100644 index 00000000..1dd02459 Binary files /dev/null and b/translated_images/custom-vision-banana-prediction.30cdff4e1d72db5d9a0be0193790a47c2b387da034e12dc1314dd57ca2131b59.hk.png differ diff --git a/translated_images/custom-vision-create-object-detector-project.32d4fb9aa8e7e7375f8a799bfce517aca970f2cb65e42d4245c5e635c734ab29.es.png b/translated_images/custom-vision-create-object-detector-project.32d4fb9aa8e7e7375f8a799bfce517aca970f2cb65e42d4245c5e635c734ab29.es.png new file mode 100644 index 00000000..64ba974b Binary files /dev/null and b/translated_images/custom-vision-create-object-detector-project.32d4fb9aa8e7e7375f8a799bfce517aca970f2cb65e42d4245c5e635c734ab29.es.png differ diff --git a/translated_images/custom-vision-create-object-detector-project.32d4fb9aa8e7e7375f8a799bfce517aca970f2cb65e42d4245c5e635c734ab29.hk.png b/translated_images/custom-vision-create-object-detector-project.32d4fb9aa8e7e7375f8a799bfce517aca970f2cb65e42d4245c5e635c734ab29.hk.png new file mode 100644 index 00000000..64ba974b Binary files /dev/null and b/translated_images/custom-vision-create-object-detector-project.32d4fb9aa8e7e7375f8a799bfce517aca970f2cb65e42d4245c5e635c734ab29.hk.png differ diff --git a/translated_images/custom-vision-create-project.cf46325b92d8b131089f6647cf5e07b664cb77850e106d66e3c057b6b69756c6.es.png b/translated_images/custom-vision-create-project.cf46325b92d8b131089f6647cf5e07b664cb77850e106d66e3c057b6b69756c6.es.png new file mode 100644 index 00000000..fd3d1f9b Binary files /dev/null and b/translated_images/custom-vision-create-project.cf46325b92d8b131089f6647cf5e07b664cb77850e106d66e3c057b6b69756c6.es.png differ diff --git a/translated_images/custom-vision-create-project.cf46325b92d8b131089f6647cf5e07b664cb77850e106d66e3c057b6b69756c6.hk.png b/translated_images/custom-vision-create-project.cf46325b92d8b131089f6647cf5e07b664cb77850e106d66e3c057b6b69756c6.hk.png new file mode 100644 index 00000000..fd3d1f9b Binary files /dev/null and b/translated_images/custom-vision-create-project.cf46325b92d8b131089f6647cf5e07b664cb77850e106d66e3c057b6b69756c6.hk.png differ diff --git a/translated_images/custom-vision-logo.d3d4e7c8a87ec9daf825e72e210576c3cbf60312577be7a139e22dd97ab7f1e6.es.png b/translated_images/custom-vision-logo.d3d4e7c8a87ec9daf825e72e210576c3cbf60312577be7a139e22dd97ab7f1e6.es.png new file mode 100644 index 00000000..f523159b Binary files /dev/null and b/translated_images/custom-vision-logo.d3d4e7c8a87ec9daf825e72e210576c3cbf60312577be7a139e22dd97ab7f1e6.es.png differ diff --git a/translated_images/custom-vision-logo.d3d4e7c8a87ec9daf825e72e210576c3cbf60312577be7a139e22dd97ab7f1e6.hk.png b/translated_images/custom-vision-logo.d3d4e7c8a87ec9daf825e72e210576c3cbf60312577be7a139e22dd97ab7f1e6.hk.png new file mode 100644 index 00000000..f523159b Binary files /dev/null and b/translated_images/custom-vision-logo.d3d4e7c8a87ec9daf825e72e210576c3cbf60312577be7a139e22dd97ab7f1e6.hk.png differ diff --git a/translated_images/custom-vision-object-detector-publish-button.34ee379fc650ccb9856c3868d0003f413b9529f102fc73c37168c98d721cc293.es.png b/translated_images/custom-vision-object-detector-publish-button.34ee379fc650ccb9856c3868d0003f413b9529f102fc73c37168c98d721cc293.es.png new file mode 100644 index 00000000..70a9bacf Binary files /dev/null and b/translated_images/custom-vision-object-detector-publish-button.34ee379fc650ccb9856c3868d0003f413b9529f102fc73c37168c98d721cc293.es.png differ diff --git a/translated_images/custom-vision-object-detector-publish-button.34ee379fc650ccb9856c3868d0003f413b9529f102fc73c37168c98d721cc293.hk.png b/translated_images/custom-vision-object-detector-publish-button.34ee379fc650ccb9856c3868d0003f413b9529f102fc73c37168c98d721cc293.hk.png new file mode 100644 index 00000000..70a9bacf Binary files /dev/null and b/translated_images/custom-vision-object-detector-publish-button.34ee379fc650ccb9856c3868d0003f413b9529f102fc73c37168c98d721cc293.hk.png differ diff --git a/translated_images/custom-vision-prediction-key-endpoint.30c569ffd0338864f319911f052d5e9b8c5066cb0800a26dd6f7ff5713130ad8.es.png b/translated_images/custom-vision-prediction-key-endpoint.30c569ffd0338864f319911f052d5e9b8c5066cb0800a26dd6f7ff5713130ad8.es.png new file mode 100644 index 00000000..9e30ab1c Binary files /dev/null and b/translated_images/custom-vision-prediction-key-endpoint.30c569ffd0338864f319911f052d5e9b8c5066cb0800a26dd6f7ff5713130ad8.es.png differ diff --git a/translated_images/custom-vision-prediction-key-endpoint.30c569ffd0338864f319911f052d5e9b8c5066cb0800a26dd6f7ff5713130ad8.hk.png b/translated_images/custom-vision-prediction-key-endpoint.30c569ffd0338864f319911f052d5e9b8c5066cb0800a26dd6f7ff5713130ad8.hk.png new file mode 100644 index 00000000..9e30ab1c Binary files /dev/null and b/translated_images/custom-vision-prediction-key-endpoint.30c569ffd0338864f319911f052d5e9b8c5066cb0800a26dd6f7ff5713130ad8.hk.png differ diff --git a/translated_images/custom-vision-publish-button.b7174e1977b0c33b8b72d4e5b1326c779e0af196f3849d09985ee2d7d5493a39.es.png b/translated_images/custom-vision-publish-button.b7174e1977b0c33b8b72d4e5b1326c779e0af196f3849d09985ee2d7d5493a39.es.png new file mode 100644 index 00000000..e9f61adc Binary files /dev/null and b/translated_images/custom-vision-publish-button.b7174e1977b0c33b8b72d4e5b1326c779e0af196f3849d09985ee2d7d5493a39.es.png differ diff --git a/translated_images/custom-vision-publish-button.b7174e1977b0c33b8b72d4e5b1326c779e0af196f3849d09985ee2d7d5493a39.hk.png b/translated_images/custom-vision-publish-button.b7174e1977b0c33b8b72d4e5b1326c779e0af196f3849d09985ee2d7d5493a39.hk.png new file mode 100644 index 00000000..e9f61adc Binary files /dev/null and b/translated_images/custom-vision-publish-button.b7174e1977b0c33b8b72d4e5b1326c779e0af196f3849d09985ee2d7d5493a39.hk.png differ diff --git a/translated_images/custom-vision-stock-prediction.942266ab1bcca3410ecdf23643b9f5f570cfab2345235074e24c51f285777613.es.png b/translated_images/custom-vision-stock-prediction.942266ab1bcca3410ecdf23643b9f5f570cfab2345235074e24c51f285777613.es.png new file mode 100644 index 00000000..a54521f7 Binary files /dev/null and b/translated_images/custom-vision-stock-prediction.942266ab1bcca3410ecdf23643b9f5f570cfab2345235074e24c51f285777613.es.png differ diff --git a/translated_images/custom-vision-stock-prediction.942266ab1bcca3410ecdf23643b9f5f570cfab2345235074e24c51f285777613.hk.png b/translated_images/custom-vision-stock-prediction.942266ab1bcca3410ecdf23643b9f5f570cfab2345235074e24c51f285777613.hk.png new file mode 100644 index 00000000..a54521f7 Binary files /dev/null and b/translated_images/custom-vision-stock-prediction.942266ab1bcca3410ecdf23643b9f5f570cfab2345235074e24c51f285777613.hk.png differ diff --git a/translated_images/dimmable-light.9ceffeb195dec1a849da718b2d71b32c35171ff7dfea9c07bbf82646a67acf6b.es.png b/translated_images/dimmable-light.9ceffeb195dec1a849da718b2d71b32c35171ff7dfea9c07bbf82646a67acf6b.es.png new file mode 100644 index 00000000..6981df8a Binary files /dev/null and b/translated_images/dimmable-light.9ceffeb195dec1a849da718b2d71b32c35171ff7dfea9c07bbf82646a67acf6b.es.png differ diff --git a/translated_images/dimmable-light.9ceffeb195dec1a849da718b2d71b32c35171ff7dfea9c07bbf82646a67acf6b.hk.png b/translated_images/dimmable-light.9ceffeb195dec1a849da718b2d71b32c35171ff7dfea9c07bbf82646a67acf6b.hk.png new file mode 100644 index 00000000..6981df8a Binary files /dev/null and b/translated_images/dimmable-light.9ceffeb195dec1a849da718b2d71b32c35171ff7dfea9c07bbf82646a67acf6b.hk.png differ diff --git a/translated_images/dmac-adc-buffers.4509aee49145c90bc2e1be472b8ed2ddfcb2b6a81ad3e559114aca55f5fff759.es.png b/translated_images/dmac-adc-buffers.4509aee49145c90bc2e1be472b8ed2ddfcb2b6a81ad3e559114aca55f5fff759.es.png new file mode 100644 index 00000000..2722c065 Binary files /dev/null and b/translated_images/dmac-adc-buffers.4509aee49145c90bc2e1be472b8ed2ddfcb2b6a81ad3e559114aca55f5fff759.es.png differ diff --git a/translated_images/dmac-adc-buffers.4509aee49145c90bc2e1be472b8ed2ddfcb2b6a81ad3e559114aca55f5fff759.hk.png b/translated_images/dmac-adc-buffers.4509aee49145c90bc2e1be472b8ed2ddfcb2b6a81ad3e559114aca55f5fff759.hk.png new file mode 100644 index 00000000..2722c065 Binary files /dev/null and b/translated_images/dmac-adc-buffers.4509aee49145c90bc2e1be472b8ed2ddfcb2b6a81ad3e559114aca55f5fff759.hk.png differ diff --git a/translated_images/dynamic-mic.8babac890a2d80dfb0874b5bf37d4b851fe2aeb9da6fd72945746176978bf3bb.es.jpg b/translated_images/dynamic-mic.8babac890a2d80dfb0874b5bf37d4b851fe2aeb9da6fd72945746176978bf3bb.es.jpg new file mode 100644 index 00000000..cce2a759 Binary files /dev/null and b/translated_images/dynamic-mic.8babac890a2d80dfb0874b5bf37d4b851fe2aeb9da6fd72945746176978bf3bb.es.jpg differ diff --git a/translated_images/dynamic-mic.8babac890a2d80dfb0874b5bf37d4b851fe2aeb9da6fd72945746176978bf3bb.hk.jpg b/translated_images/dynamic-mic.8babac890a2d80dfb0874b5bf37d4b851fe2aeb9da6fd72945746176978bf3bb.hk.jpg new file mode 100644 index 00000000..cce2a759 Binary files /dev/null and b/translated_images/dynamic-mic.8babac890a2d80dfb0874b5bf37d4b851fe2aeb9da6fd72945746176978bf3bb.hk.jpg differ diff --git a/translated_images/favicon.37b561214b36d454f9fd1f725d77f310fe256eb88f2a0ae08b9cb18aeb30650c.es.png b/translated_images/favicon.37b561214b36d454f9fd1f725d77f310fe256eb88f2a0ae08b9cb18aeb30650c.es.png new file mode 100644 index 00000000..26e0ae43 Binary files /dev/null and b/translated_images/favicon.37b561214b36d454f9fd1f725d77f310fe256eb88f2a0ae08b9cb18aeb30650c.es.png differ diff --git a/translated_images/favicon.37b561214b36d454f9fd1f725d77f310fe256eb88f2a0ae08b9cb18aeb30650c.hk.png b/translated_images/favicon.37b561214b36d454f9fd1f725d77f310fe256eb88f2a0ae08b9cb18aeb30650c.hk.png new file mode 100644 index 00000000..26e0ae43 Binary files /dev/null and b/translated_images/favicon.37b561214b36d454f9fd1f725d77f310fe256eb88f2a0ae08b9cb18aeb30650c.hk.png differ diff --git a/translated_images/fetch-decode-execute.2fd6f150f6280392807f4475382319abd0cee0b90058e1735444d6baa6f2078c.es.png b/translated_images/fetch-decode-execute.2fd6f150f6280392807f4475382319abd0cee0b90058e1735444d6baa6f2078c.es.png new file mode 100644 index 00000000..a5d549fd Binary files /dev/null and b/translated_images/fetch-decode-execute.2fd6f150f6280392807f4475382319abd0cee0b90058e1735444d6baa6f2078c.es.png differ diff --git a/translated_images/fetch-decode-execute.2fd6f150f6280392807f4475382319abd0cee0b90058e1735444d6baa6f2078c.hk.png b/translated_images/fetch-decode-execute.2fd6f150f6280392807f4475382319abd0cee0b90058e1735444d6baa6f2078c.hk.png new file mode 100644 index 00000000..a5d549fd Binary files /dev/null and b/translated_images/fetch-decode-execute.2fd6f150f6280392807f4475382319abd0cee0b90058e1735444d6baa6f2078c.hk.png differ diff --git a/translated_images/fruit-quality-detector-message-flow.adf2a65da8fd8741ac7af11361574de89adc126785d67606bb4d2ec00467e380.es.png b/translated_images/fruit-quality-detector-message-flow.adf2a65da8fd8741ac7af11361574de89adc126785d67606bb4d2ec00467e380.es.png new file mode 100644 index 00000000..a251745c Binary files /dev/null and b/translated_images/fruit-quality-detector-message-flow.adf2a65da8fd8741ac7af11361574de89adc126785d67606bb4d2ec00467e380.es.png differ diff --git a/translated_images/fruit-quality-detector-message-flow.adf2a65da8fd8741ac7af11361574de89adc126785d67606bb4d2ec00467e380.hk.png b/translated_images/fruit-quality-detector-message-flow.adf2a65da8fd8741ac7af11361574de89adc126785d67606bb4d2ec00467e380.hk.png new file mode 100644 index 00000000..a251745c Binary files /dev/null and b/translated_images/fruit-quality-detector-message-flow.adf2a65da8fd8741ac7af11361574de89adc126785d67606bb4d2ec00467e380.hk.png differ diff --git a/translated_images/gdd-calculation-corn.64a58b7a7afcd0dfd46ff733996d939f17f4f3feac9f0d1c632be3523e51ebd9.es.png b/translated_images/gdd-calculation-corn.64a58b7a7afcd0dfd46ff733996d939f17f4f3feac9f0d1c632be3523e51ebd9.es.png new file mode 100644 index 00000000..bb97d28e Binary files /dev/null and b/translated_images/gdd-calculation-corn.64a58b7a7afcd0dfd46ff733996d939f17f4f3feac9f0d1c632be3523e51ebd9.es.png differ diff --git a/translated_images/gdd-calculation-corn.64a58b7a7afcd0dfd46ff733996d939f17f4f3feac9f0d1c632be3523e51ebd9.hk.png b/translated_images/gdd-calculation-corn.64a58b7a7afcd0dfd46ff733996d939f17f4f3feac9f0d1c632be3523e51ebd9.hk.png new file mode 100644 index 00000000..bb97d28e Binary files /dev/null and b/translated_images/gdd-calculation-corn.64a58b7a7afcd0dfd46ff733996d939f17f4f3feac9f0d1c632be3523e51ebd9.hk.png differ diff --git a/translated_images/gdd-calculation-strawberries.59f57db94b22adb8ff6efb951ace33af104a1c6ccca3ffb0f8169c14cb160c90.es.png b/translated_images/gdd-calculation-strawberries.59f57db94b22adb8ff6efb951ace33af104a1c6ccca3ffb0f8169c14cb160c90.es.png new file mode 100644 index 00000000..e34dea22 Binary files /dev/null and b/translated_images/gdd-calculation-strawberries.59f57db94b22adb8ff6efb951ace33af104a1c6ccca3ffb0f8169c14cb160c90.es.png differ diff --git a/translated_images/gdd-calculation-strawberries.59f57db94b22adb8ff6efb951ace33af104a1c6ccca3ffb0f8169c14cb160c90.hk.png b/translated_images/gdd-calculation-strawberries.59f57db94b22adb8ff6efb951ace33af104a1c6ccca3ffb0f8169c14cb160c90.hk.png new file mode 100644 index 00000000..e34dea22 Binary files /dev/null and b/translated_images/gdd-calculation-strawberries.59f57db94b22adb8ff6efb951ace33af104a1c6ccca3ffb0f8169c14cb160c90.hk.png differ diff --git a/translated_images/gdd-calculation.79b3660f9c5757aa92dc2dd2cdde75344e2d2c1565c4b3151640f7887edc0275.es.png b/translated_images/gdd-calculation.79b3660f9c5757aa92dc2dd2cdde75344e2d2c1565c4b3151640f7887edc0275.es.png new file mode 100644 index 00000000..fa863501 Binary files /dev/null and b/translated_images/gdd-calculation.79b3660f9c5757aa92dc2dd2cdde75344e2d2c1565c4b3151640f7887edc0275.es.png differ diff --git a/translated_images/gdd-calculation.79b3660f9c5757aa92dc2dd2cdde75344e2d2c1565c4b3151640f7887edc0275.hk.png b/translated_images/gdd-calculation.79b3660f9c5757aa92dc2dd2cdde75344e2d2c1565c4b3151640f7887edc0275.hk.png new file mode 100644 index 00000000..fa863501 Binary files /dev/null and b/translated_images/gdd-calculation.79b3660f9c5757aa92dc2dd2cdde75344e2d2c1565c4b3151640f7887edc0275.hk.png differ diff --git a/translated_images/gdd-jupyter-notebook.c5b52cf21094f158a61f47f455490fd95f1729777ff90861a4521820bf354cdc.es.png b/translated_images/gdd-jupyter-notebook.c5b52cf21094f158a61f47f455490fd95f1729777ff90861a4521820bf354cdc.es.png new file mode 100644 index 00000000..0d0e0c48 Binary files /dev/null and b/translated_images/gdd-jupyter-notebook.c5b52cf21094f158a61f47f455490fd95f1729777ff90861a4521820bf354cdc.es.png differ diff --git a/translated_images/gdd-jupyter-notebook.c5b52cf21094f158a61f47f455490fd95f1729777ff90861a4521820bf354cdc.hk.png b/translated_images/gdd-jupyter-notebook.c5b52cf21094f158a61f47f455490fd95f1729777ff90861a4521820bf354cdc.hk.png new file mode 100644 index 00000000..0d0e0c48 Binary files /dev/null and b/translated_images/gdd-jupyter-notebook.c5b52cf21094f158a61f47f455490fd95f1729777ff90861a4521820bf354cdc.hk.png differ diff --git a/translated_images/geofence-crossing-inaccurate-gps.6a3ed911202ad9cabb66d3964888cec03a42c61d5b8f536ad5bdc99716b370f5.es.png b/translated_images/geofence-crossing-inaccurate-gps.6a3ed911202ad9cabb66d3964888cec03a42c61d5b8f536ad5bdc99716b370f5.es.png new file mode 100644 index 00000000..6f79a498 Binary files /dev/null and b/translated_images/geofence-crossing-inaccurate-gps.6a3ed911202ad9cabb66d3964888cec03a42c61d5b8f536ad5bdc99716b370f5.es.png differ diff --git a/translated_images/geofence-crossing-inaccurate-gps.6a3ed911202ad9cabb66d3964888cec03a42c61d5b8f536ad5bdc99716b370f5.hk.png b/translated_images/geofence-crossing-inaccurate-gps.6a3ed911202ad9cabb66d3964888cec03a42c61d5b8f536ad5bdc99716b370f5.hk.png new file mode 100644 index 00000000..6f79a498 Binary files /dev/null and b/translated_images/geofence-crossing-inaccurate-gps.6a3ed911202ad9cabb66d3964888cec03a42c61d5b8f536ad5bdc99716b370f5.hk.png differ diff --git a/translated_images/geofence-examples.172fbc534665769f6e1a1ddcf75e3b25183cd10354c80cc603ba44b635390e1a.es.png b/translated_images/geofence-examples.172fbc534665769f6e1a1ddcf75e3b25183cd10354c80cc603ba44b635390e1a.es.png new file mode 100644 index 00000000..8527d4cd Binary files /dev/null and b/translated_images/geofence-examples.172fbc534665769f6e1a1ddcf75e3b25183cd10354c80cc603ba44b635390e1a.es.png differ diff --git a/translated_images/geofence-examples.172fbc534665769f6e1a1ddcf75e3b25183cd10354c80cc603ba44b635390e1a.hk.png b/translated_images/geofence-examples.172fbc534665769f6e1a1ddcf75e3b25183cd10354c80cc603ba44b635390e1a.hk.png new file mode 100644 index 00000000..8527d4cd Binary files /dev/null and b/translated_images/geofence-examples.172fbc534665769f6e1a1ddcf75e3b25183cd10354c80cc603ba44b635390e1a.hk.png differ diff --git a/translated_images/gps-satellites.04acf1148fe25fbf1586bc2e8ba698e8d79b79a50c36824b38417dd13372b90f.es.png b/translated_images/gps-satellites.04acf1148fe25fbf1586bc2e8ba698e8d79b79a50c36824b38417dd13372b90f.es.png new file mode 100644 index 00000000..8597bf4d Binary files /dev/null and b/translated_images/gps-satellites.04acf1148fe25fbf1586bc2e8ba698e8d79b79a50c36824b38417dd13372b90f.es.png differ diff --git a/translated_images/gps-satellites.04acf1148fe25fbf1586bc2e8ba698e8d79b79a50c36824b38417dd13372b90f.hk.png b/translated_images/gps-satellites.04acf1148fe25fbf1586bc2e8ba698e8d79b79a50c36824b38417dd13372b90f.hk.png new file mode 100644 index 00000000..8597bf4d Binary files /dev/null and b/translated_images/gps-satellites.04acf1148fe25fbf1586bc2e8ba698e8d79b79a50c36824b38417dd13372b90f.hk.png differ diff --git a/translated_images/gps-telemetry-iot-hub-functions.24d3fa5592455e9f4e2fe73856b40c3915a292b90263c31d652acfd976cfedd8.es.png b/translated_images/gps-telemetry-iot-hub-functions.24d3fa5592455e9f4e2fe73856b40c3915a292b90263c31d652acfd976cfedd8.es.png new file mode 100644 index 00000000..3bf24358 Binary files /dev/null and b/translated_images/gps-telemetry-iot-hub-functions.24d3fa5592455e9f4e2fe73856b40c3915a292b90263c31d652acfd976cfedd8.es.png differ diff --git a/translated_images/gps-telemetry-iot-hub-functions.24d3fa5592455e9f4e2fe73856b40c3915a292b90263c31d652acfd976cfedd8.hk.png b/translated_images/gps-telemetry-iot-hub-functions.24d3fa5592455e9f4e2fe73856b40c3915a292b90263c31d652acfd976cfedd8.hk.png new file mode 100644 index 00000000..3bf24358 Binary files /dev/null and b/translated_images/gps-telemetry-iot-hub-functions.24d3fa5592455e9f4e2fe73856b40c3915a292b90263c31d652acfd976cfedd8.hk.png differ diff --git a/translated_images/gps-telemetry-iot-hub.8115335d51cd2c1285d20e9d1b18cf685e59a8e093e7797291ef173445af6f3d.es.png b/translated_images/gps-telemetry-iot-hub.8115335d51cd2c1285d20e9d1b18cf685e59a8e093e7797291ef173445af6f3d.es.png new file mode 100644 index 00000000..562f66d2 Binary files /dev/null and b/translated_images/gps-telemetry-iot-hub.8115335d51cd2c1285d20e9d1b18cf685e59a8e093e7797291ef173445af6f3d.es.png differ diff --git a/translated_images/gps-telemetry-iot-hub.8115335d51cd2c1285d20e9d1b18cf685e59a8e093e7797291ef173445af6f3d.hk.png b/translated_images/gps-telemetry-iot-hub.8115335d51cd2c1285d20e9d1b18cf685e59a8e093e7797291ef173445af6f3d.hk.png new file mode 100644 index 00000000..562f66d2 Binary files /dev/null and b/translated_images/gps-telemetry-iot-hub.8115335d51cd2c1285d20e9d1b18cf685e59a8e093e7797291ef173445af6f3d.hk.png differ diff --git a/translated_images/grove-base-hat-ribbon-cable.501fed202fcf73b11b2b68f6d246189f7d15d3e4423c572ddee79d77b4632b47.es.png b/translated_images/grove-base-hat-ribbon-cable.501fed202fcf73b11b2b68f6d246189f7d15d3e4423c572ddee79d77b4632b47.es.png new file mode 100644 index 00000000..2f50d53a Binary files /dev/null and b/translated_images/grove-base-hat-ribbon-cable.501fed202fcf73b11b2b68f6d246189f7d15d3e4423c572ddee79d77b4632b47.es.png differ diff --git a/translated_images/grove-base-hat-ribbon-cable.501fed202fcf73b11b2b68f6d246189f7d15d3e4423c572ddee79d77b4632b47.hk.png b/translated_images/grove-base-hat-ribbon-cable.501fed202fcf73b11b2b68f6d246189f7d15d3e4423c572ddee79d77b4632b47.hk.png new file mode 100644 index 00000000..2f50d53a Binary files /dev/null and b/translated_images/grove-base-hat-ribbon-cable.501fed202fcf73b11b2b68f6d246189f7d15d3e4423c572ddee79d77b4632b47.hk.png differ diff --git a/translated_images/grove-button.a70cfbb809a8563681003250cf5b06d68cdcc68624f9e2f493d5a534ae2da1e5.es.png b/translated_images/grove-button.a70cfbb809a8563681003250cf5b06d68cdcc68624f9e2f493d5a534ae2da1e5.es.png new file mode 100644 index 00000000..de7f343e Binary files /dev/null and b/translated_images/grove-button.a70cfbb809a8563681003250cf5b06d68cdcc68624f9e2f493d5a534ae2da1e5.es.png differ diff --git a/translated_images/grove-button.a70cfbb809a8563681003250cf5b06d68cdcc68624f9e2f493d5a534ae2da1e5.hk.png b/translated_images/grove-button.a70cfbb809a8563681003250cf5b06d68cdcc68624f9e2f493d5a534ae2da1e5.hk.png new file mode 100644 index 00000000..de7f343e Binary files /dev/null and b/translated_images/grove-button.a70cfbb809a8563681003250cf5b06d68cdcc68624f9e2f493d5a534ae2da1e5.hk.png differ diff --git a/translated_images/grove-capacitive-soil-moisture-sensor.e7f0776cce30e78be5cc5a07839385fd6718857f31b5bf5ad3d0c73c83b2f0ef.es.png b/translated_images/grove-capacitive-soil-moisture-sensor.e7f0776cce30e78be5cc5a07839385fd6718857f31b5bf5ad3d0c73c83b2f0ef.es.png new file mode 100644 index 00000000..c8b1a544 Binary files /dev/null and b/translated_images/grove-capacitive-soil-moisture-sensor.e7f0776cce30e78be5cc5a07839385fd6718857f31b5bf5ad3d0c73c83b2f0ef.es.png differ diff --git a/translated_images/grove-capacitive-soil-moisture-sensor.e7f0776cce30e78be5cc5a07839385fd6718857f31b5bf5ad3d0c73c83b2f0ef.hk.png b/translated_images/grove-capacitive-soil-moisture-sensor.e7f0776cce30e78be5cc5a07839385fd6718857f31b5bf5ad3d0c73c83b2f0ef.hk.png new file mode 100644 index 00000000..c8b1a544 Binary files /dev/null and b/translated_images/grove-capacitive-soil-moisture-sensor.e7f0776cce30e78be5cc5a07839385fd6718857f31b5bf5ad3d0c73c83b2f0ef.hk.png differ diff --git a/translated_images/grove-dht11.07f8eafceee170043efbb53e1d15722bd4e00fbaa9ff74290b57e9f66eb82c17.es.png b/translated_images/grove-dht11.07f8eafceee170043efbb53e1d15722bd4e00fbaa9ff74290b57e9f66eb82c17.es.png new file mode 100644 index 00000000..17d1151d Binary files /dev/null and b/translated_images/grove-dht11.07f8eafceee170043efbb53e1d15722bd4e00fbaa9ff74290b57e9f66eb82c17.es.png differ diff --git a/translated_images/grove-dht11.07f8eafceee170043efbb53e1d15722bd4e00fbaa9ff74290b57e9f66eb82c17.hk.png b/translated_images/grove-dht11.07f8eafceee170043efbb53e1d15722bd4e00fbaa9ff74290b57e9f66eb82c17.hk.png new file mode 100644 index 00000000..17d1151d Binary files /dev/null and b/translated_images/grove-dht11.07f8eafceee170043efbb53e1d15722bd4e00fbaa9ff74290b57e9f66eb82c17.hk.png differ diff --git a/translated_images/grove-gps-sensor.247943bf69b03f0d1820ef6ed10c587f9b650e8db55b936851c92412180bd3e2.es.png b/translated_images/grove-gps-sensor.247943bf69b03f0d1820ef6ed10c587f9b650e8db55b936851c92412180bd3e2.es.png new file mode 100644 index 00000000..ffafc104 Binary files /dev/null and b/translated_images/grove-gps-sensor.247943bf69b03f0d1820ef6ed10c587f9b650e8db55b936851c92412180bd3e2.es.png differ diff --git a/translated_images/grove-gps-sensor.247943bf69b03f0d1820ef6ed10c587f9b650e8db55b936851c92412180bd3e2.hk.png b/translated_images/grove-gps-sensor.247943bf69b03f0d1820ef6ed10c587f9b650e8db55b936851c92412180bd3e2.hk.png new file mode 100644 index 00000000..ffafc104 Binary files /dev/null and b/translated_images/grove-gps-sensor.247943bf69b03f0d1820ef6ed10c587f9b650e8db55b936851c92412180bd3e2.hk.png differ diff --git a/translated_images/grove-led.6c853be93f473cf2c439cfc74bb1064732b22251a83cedf66e62f783f9cc1a79.es.png b/translated_images/grove-led.6c853be93f473cf2c439cfc74bb1064732b22251a83cedf66e62f783f9cc1a79.es.png new file mode 100644 index 00000000..e3d86f8c Binary files /dev/null and b/translated_images/grove-led.6c853be93f473cf2c439cfc74bb1064732b22251a83cedf66e62f783f9cc1a79.es.png differ diff --git a/translated_images/grove-led.6c853be93f473cf2c439cfc74bb1064732b22251a83cedf66e62f783f9cc1a79.hk.png b/translated_images/grove-led.6c853be93f473cf2c439cfc74bb1064732b22251a83cedf66e62f783f9cc1a79.hk.png new file mode 100644 index 00000000..e3d86f8c Binary files /dev/null and b/translated_images/grove-led.6c853be93f473cf2c439cfc74bb1064732b22251a83cedf66e62f783f9cc1a79.hk.png differ diff --git a/translated_images/grove-light-sensor.b8127b7c434e632d6bcdb57587a14e9ef69a268a22df95d08628f62b8fa5505c.es.png b/translated_images/grove-light-sensor.b8127b7c434e632d6bcdb57587a14e9ef69a268a22df95d08628f62b8fa5505c.es.png new file mode 100644 index 00000000..3a4445ee Binary files /dev/null and b/translated_images/grove-light-sensor.b8127b7c434e632d6bcdb57587a14e9ef69a268a22df95d08628f62b8fa5505c.es.png differ diff --git a/translated_images/grove-light-sensor.b8127b7c434e632d6bcdb57587a14e9ef69a268a22df95d08628f62b8fa5505c.hk.png b/translated_images/grove-light-sensor.b8127b7c434e632d6bcdb57587a14e9ef69a268a22df95d08628f62b8fa5505c.hk.png new file mode 100644 index 00000000..3a4445ee Binary files /dev/null and b/translated_images/grove-light-sensor.b8127b7c434e632d6bcdb57587a14e9ef69a268a22df95d08628f62b8fa5505c.hk.png differ diff --git a/translated_images/grove-relay-labelled.293e068f5c3c2a199bd7892f2661fdc9e10c920b535cfed317fbd6d1d4ae1168.es.png b/translated_images/grove-relay-labelled.293e068f5c3c2a199bd7892f2661fdc9e10c920b535cfed317fbd6d1d4ae1168.es.png new file mode 100644 index 00000000..b2bf4d3f Binary files /dev/null and b/translated_images/grove-relay-labelled.293e068f5c3c2a199bd7892f2661fdc9e10c920b535cfed317fbd6d1d4ae1168.es.png differ diff --git a/translated_images/grove-relay-labelled.293e068f5c3c2a199bd7892f2661fdc9e10c920b535cfed317fbd6d1d4ae1168.hk.png b/translated_images/grove-relay-labelled.293e068f5c3c2a199bd7892f2661fdc9e10c920b535cfed317fbd6d1d4ae1168.hk.png new file mode 100644 index 00000000..b2bf4d3f Binary files /dev/null and b/translated_images/grove-relay-labelled.293e068f5c3c2a199bd7892f2661fdc9e10c920b535cfed317fbd6d1d4ae1168.hk.png differ diff --git a/translated_images/grove-relay.d426958ca210fbd0fb7983d7edc069d46c73a8b0a099d94797bd756f7b6bb6be.es.png b/translated_images/grove-relay.d426958ca210fbd0fb7983d7edc069d46c73a8b0a099d94797bd756f7b6bb6be.es.png new file mode 100644 index 00000000..467cedcd Binary files /dev/null and b/translated_images/grove-relay.d426958ca210fbd0fb7983d7edc069d46c73a8b0a099d94797bd756f7b6bb6be.es.png differ diff --git a/translated_images/grove-relay.d426958ca210fbd0fb7983d7edc069d46c73a8b0a099d94797bd756f7b6bb6be.hk.png b/translated_images/grove-relay.d426958ca210fbd0fb7983d7edc069d46c73a8b0a099d94797bd756f7b6bb6be.hk.png new file mode 100644 index 00000000..467cedcd Binary files /dev/null and b/translated_images/grove-relay.d426958ca210fbd0fb7983d7edc069d46c73a8b0a099d94797bd756f7b6bb6be.hk.png differ diff --git a/translated_images/grove-time-of-flight-sensor.d82ff2165bfded9f485de54d8d07195a6270a602696825fca19f629ddfe94e86.es.png b/translated_images/grove-time-of-flight-sensor.d82ff2165bfded9f485de54d8d07195a6270a602696825fca19f629ddfe94e86.es.png new file mode 100644 index 00000000..88efaa59 Binary files /dev/null and b/translated_images/grove-time-of-flight-sensor.d82ff2165bfded9f485de54d8d07195a6270a602696825fca19f629ddfe94e86.es.png differ diff --git a/translated_images/grove-time-of-flight-sensor.d82ff2165bfded9f485de54d8d07195a6270a602696825fca19f629ddfe94e86.hk.png b/translated_images/grove-time-of-flight-sensor.d82ff2165bfded9f485de54d8d07195a6270a602696825fca19f629ddfe94e86.hk.png new file mode 100644 index 00000000..88efaa59 Binary files /dev/null and b/translated_images/grove-time-of-flight-sensor.d82ff2165bfded9f485de54d8d07195a6270a602696825fca19f629ddfe94e86.hk.png differ diff --git a/translated_images/gsm-calculation-example.99f9803b4f29e97668e7c15412136c0c399ab12dbba0b89596fdae9d8aedb6fb.es.png b/translated_images/gsm-calculation-example.99f9803b4f29e97668e7c15412136c0c399ab12dbba0b89596fdae9d8aedb6fb.es.png new file mode 100644 index 00000000..6197ed95 Binary files /dev/null and b/translated_images/gsm-calculation-example.99f9803b4f29e97668e7c15412136c0c399ab12dbba0b89596fdae9d8aedb6fb.es.png differ diff --git a/translated_images/gsm-calculation-example.99f9803b4f29e97668e7c15412136c0c399ab12dbba0b89596fdae9d8aedb6fb.hk.png b/translated_images/gsm-calculation-example.99f9803b4f29e97668e7c15412136c0c399ab12dbba0b89596fdae9d8aedb6fb.hk.png new file mode 100644 index 00000000..6197ed95 Binary files /dev/null and b/translated_images/gsm-calculation-example.99f9803b4f29e97668e7c15412136c0c399ab12dbba0b89596fdae9d8aedb6fb.hk.png differ diff --git a/translated_images/gsm-calculation.6da38c6201eec14e7573bb2647aa18892883193553d23c9d77e5dc681522dfb2.es.png b/translated_images/gsm-calculation.6da38c6201eec14e7573bb2647aa18892883193553d23c9d77e5dc681522dfb2.es.png new file mode 100644 index 00000000..ec7768da Binary files /dev/null and b/translated_images/gsm-calculation.6da38c6201eec14e7573bb2647aa18892883193553d23c9d77e5dc681522dfb2.es.png differ diff --git a/translated_images/gsm-calculation.6da38c6201eec14e7573bb2647aa18892883193553d23c9d77e5dc681522dfb2.hk.png b/translated_images/gsm-calculation.6da38c6201eec14e7573bb2647aa18892883193553d23c9d77e5dc681522dfb2.hk.png new file mode 100644 index 00000000..ec7768da Binary files /dev/null and b/translated_images/gsm-calculation.6da38c6201eec14e7573bb2647aa18892883193553d23c9d77e5dc681522dfb2.hk.png differ diff --git a/translated_images/i2c.83da845dde02256bdd462dbe0d5145461416b74930571b89d1ae142841eeb584.es.png b/translated_images/i2c.83da845dde02256bdd462dbe0d5145461416b74930571b89d1ae142841eeb584.es.png new file mode 100644 index 00000000..f68bf461 Binary files /dev/null and b/translated_images/i2c.83da845dde02256bdd462dbe0d5145461416b74930571b89d1ae142841eeb584.es.png differ diff --git a/translated_images/i2c.83da845dde02256bdd462dbe0d5145461416b74930571b89d1ae142841eeb584.hk.png b/translated_images/i2c.83da845dde02256bdd462dbe0d5145461416b74930571b89d1ae142841eeb584.hk.png new file mode 100644 index 00000000..f68bf461 Binary files /dev/null and b/translated_images/i2c.83da845dde02256bdd462dbe0d5145461416b74930571b89d1ae142841eeb584.hk.png differ diff --git a/translated_images/image-classifier-cashews-tomato.bc2e16ab8f05cf9ac0f59f73e32efc4227f9a5b601b90b2c60f436694547a965.es.png b/translated_images/image-classifier-cashews-tomato.bc2e16ab8f05cf9ac0f59f73e32efc4227f9a5b601b90b2c60f436694547a965.es.png new file mode 100644 index 00000000..73e34cfe Binary files /dev/null and b/translated_images/image-classifier-cashews-tomato.bc2e16ab8f05cf9ac0f59f73e32efc4227f9a5b601b90b2c60f436694547a965.es.png differ diff --git a/translated_images/image-classifier-cashews-tomato.bc2e16ab8f05cf9ac0f59f73e32efc4227f9a5b601b90b2c60f436694547a965.hk.png b/translated_images/image-classifier-cashews-tomato.bc2e16ab8f05cf9ac0f59f73e32efc4227f9a5b601b90b2c60f436694547a965.hk.png new file mode 100644 index 00000000..73e34cfe Binary files /dev/null and b/translated_images/image-classifier-cashews-tomato.bc2e16ab8f05cf9ac0f59f73e32efc4227f9a5b601b90b2c60f436694547a965.hk.png differ diff --git a/translated_images/image-upload-bananas.0751639f3815e0ec42bdbc6254d1e4357a185834d1ae10c9948a0e7d6d336695.es.png b/translated_images/image-upload-bananas.0751639f3815e0ec42bdbc6254d1e4357a185834d1ae10c9948a0e7d6d336695.es.png new file mode 100644 index 00000000..21cc6bd0 Binary files /dev/null and b/translated_images/image-upload-bananas.0751639f3815e0ec42bdbc6254d1e4357a185834d1ae10c9948a0e7d6d336695.es.png differ diff --git a/translated_images/image-upload-bananas.0751639f3815e0ec42bdbc6254d1e4357a185834d1ae10c9948a0e7d6d336695.hk.png b/translated_images/image-upload-bananas.0751639f3815e0ec42bdbc6254d1e4357a185834d1ae10c9948a0e7d6d336695.hk.png new file mode 100644 index 00000000..21cc6bd0 Binary files /dev/null and b/translated_images/image-upload-bananas.0751639f3815e0ec42bdbc6254d1e4357a185834d1ae10c9948a0e7d6d336695.hk.png differ diff --git a/translated_images/image-upload-object-detector.77c7892c3093cb59b79018edecd678749a75d71a099bc8a2d2f2f76320f88a5b.es.png b/translated_images/image-upload-object-detector.77c7892c3093cb59b79018edecd678749a75d71a099bc8a2d2f2f76320f88a5b.es.png new file mode 100644 index 00000000..9c7deb23 Binary files /dev/null and b/translated_images/image-upload-object-detector.77c7892c3093cb59b79018edecd678749a75d71a099bc8a2d2f2f76320f88a5b.es.png differ diff --git a/translated_images/image-upload-object-detector.77c7892c3093cb59b79018edecd678749a75d71a099bc8a2d2f2f76320f88a5b.hk.png b/translated_images/image-upload-object-detector.77c7892c3093cb59b79018edecd678749a75d71a099bc8a2d2f2f76320f88a5b.hk.png new file mode 100644 index 00000000..9c7deb23 Binary files /dev/null and b/translated_images/image-upload-object-detector.77c7892c3093cb59b79018edecd678749a75d71a099bc8a2d2f2f76320f88a5b.hk.png differ diff --git a/translated_images/iot-device-and-hacked-device-connecting-encryption.5941aff601fc978f979e46f2849b573564eeb4a4dc5b52f669f62745397492fb.es.png b/translated_images/iot-device-and-hacked-device-connecting-encryption.5941aff601fc978f979e46f2849b573564eeb4a4dc5b52f669f62745397492fb.es.png new file mode 100644 index 00000000..ddc9958b Binary files /dev/null and b/translated_images/iot-device-and-hacked-device-connecting-encryption.5941aff601fc978f979e46f2849b573564eeb4a4dc5b52f669f62745397492fb.es.png differ diff --git a/translated_images/iot-device-and-hacked-device-connecting-encryption.5941aff601fc978f979e46f2849b573564eeb4a4dc5b52f669f62745397492fb.hk.png b/translated_images/iot-device-and-hacked-device-connecting-encryption.5941aff601fc978f979e46f2849b573564eeb4a4dc5b52f669f62745397492fb.hk.png new file mode 100644 index 00000000..ddc9958b Binary files /dev/null and b/translated_images/iot-device-and-hacked-device-connecting-encryption.5941aff601fc978f979e46f2849b573564eeb4a4dc5b52f669f62745397492fb.hk.png differ diff --git a/translated_images/iot-device-and-hacked-device-connecting.e0671675df74d6d99eb1dedb5a670e606f698efa6202b1ad4c8ae548db299cc6.es.png b/translated_images/iot-device-and-hacked-device-connecting.e0671675df74d6d99eb1dedb5a670e606f698efa6202b1ad4c8ae548db299cc6.es.png new file mode 100644 index 00000000..d181210a Binary files /dev/null and b/translated_images/iot-device-and-hacked-device-connecting.e0671675df74d6d99eb1dedb5a670e606f698efa6202b1ad4c8ae548db299cc6.es.png differ diff --git a/translated_images/iot-device-and-hacked-device-connecting.e0671675df74d6d99eb1dedb5a670e606f698efa6202b1ad4c8ae548db299cc6.hk.png b/translated_images/iot-device-and-hacked-device-connecting.e0671675df74d6d99eb1dedb5a670e606f698efa6202b1ad4c8ae548db299cc6.hk.png new file mode 100644 index 00000000..d181210a Binary files /dev/null and b/translated_images/iot-device-and-hacked-device-connecting.e0671675df74d6d99eb1dedb5a670e606f698efa6202b1ad4c8ae548db299cc6.hk.png differ diff --git a/translated_images/iot-for-beginners.95958e2ed1900917f0c2173dd725ae0a2c1af97b9a26e56c76d3c8c8925f32ee.es.png b/translated_images/iot-for-beginners.95958e2ed1900917f0c2173dd725ae0a2c1af97b9a26e56c76d3c8c8925f32ee.es.png new file mode 100644 index 00000000..a00ab427 Binary files /dev/null and b/translated_images/iot-for-beginners.95958e2ed1900917f0c2173dd725ae0a2c1af97b9a26e56c76d3c8c8925f32ee.es.png differ diff --git a/translated_images/iot-for-beginners.95958e2ed1900917f0c2173dd725ae0a2c1af97b9a26e56c76d3c8c8925f32ee.hk.png b/translated_images/iot-for-beginners.95958e2ed1900917f0c2173dd725ae0a2c1af97b9a26e56c76d3c8c8925f32ee.hk.png new file mode 100644 index 00000000..a00ab427 Binary files /dev/null and b/translated_images/iot-for-beginners.95958e2ed1900917f0c2173dd725ae0a2c1af97b9a26e56c76d3c8c8925f32ee.hk.png differ diff --git a/translated_images/iot-hub-cloud-to-device-message.f4f21fea772cc20ba15004d853b805f6c01b612d257df6295ed7618550308aaf.es.png b/translated_images/iot-hub-cloud-to-device-message.f4f21fea772cc20ba15004d853b805f6c01b612d257df6295ed7618550308aaf.es.png new file mode 100644 index 00000000..dedb38a3 Binary files /dev/null and b/translated_images/iot-hub-cloud-to-device-message.f4f21fea772cc20ba15004d853b805f6c01b612d257df6295ed7618550308aaf.es.png differ diff --git a/translated_images/iot-hub-cloud-to-device-message.f4f21fea772cc20ba15004d853b805f6c01b612d257df6295ed7618550308aaf.hk.png b/translated_images/iot-hub-cloud-to-device-message.f4f21fea772cc20ba15004d853b805f6c01b612d257df6295ed7618550308aaf.hk.png new file mode 100644 index 00000000..dedb38a3 Binary files /dev/null and b/translated_images/iot-hub-cloud-to-device-message.f4f21fea772cc20ba15004d853b805f6c01b612d257df6295ed7618550308aaf.hk.png differ diff --git a/translated_images/iot-hub-device-to-cloud-message.e46e584d87f35fd952657f0b566dcac59473fe960d87c96fa54a4b5438ddc31f.es.png b/translated_images/iot-hub-device-to-cloud-message.e46e584d87f35fd952657f0b566dcac59473fe960d87c96fa54a4b5438ddc31f.es.png new file mode 100644 index 00000000..2b34487d Binary files /dev/null and b/translated_images/iot-hub-device-to-cloud-message.e46e584d87f35fd952657f0b566dcac59473fe960d87c96fa54a4b5438ddc31f.es.png differ diff --git a/translated_images/iot-hub-device-to-cloud-message.e46e584d87f35fd952657f0b566dcac59473fe960d87c96fa54a4b5438ddc31f.hk.png b/translated_images/iot-hub-device-to-cloud-message.e46e584d87f35fd952657f0b566dcac59473fe960d87c96fa54a4b5438ddc31f.hk.png new file mode 100644 index 00000000..2b34487d Binary files /dev/null and b/translated_images/iot-hub-device-to-cloud-message.e46e584d87f35fd952657f0b566dcac59473fe960d87c96fa54a4b5438ddc31f.hk.png differ diff --git a/translated_images/iot-hub-device-twins.7055a60fc5e2331c44298ae157d72edec0022910b1a4bf4bc93f39c620878b68.es.png b/translated_images/iot-hub-device-twins.7055a60fc5e2331c44298ae157d72edec0022910b1a4bf4bc93f39c620878b68.es.png new file mode 100644 index 00000000..1cae68ed Binary files /dev/null and b/translated_images/iot-hub-device-twins.7055a60fc5e2331c44298ae157d72edec0022910b1a4bf4bc93f39c620878b68.es.png differ diff --git a/translated_images/iot-hub-device-twins.7055a60fc5e2331c44298ae157d72edec0022910b1a4bf4bc93f39c620878b68.hk.png b/translated_images/iot-hub-device-twins.7055a60fc5e2331c44298ae157d72edec0022910b1a4bf4bc93f39c620878b68.hk.png new file mode 100644 index 00000000..1cae68ed Binary files /dev/null and b/translated_images/iot-hub-device-twins.7055a60fc5e2331c44298ae157d72edec0022910b1a4bf4bc93f39c620878b68.hk.png differ diff --git a/translated_images/iot-hub-direct-method-request.86a5026e91f4ca1864e2043fab4b8199e42c2c6efc1209973cb56f199646b171.es.png b/translated_images/iot-hub-direct-method-request.86a5026e91f4ca1864e2043fab4b8199e42c2c6efc1209973cb56f199646b171.es.png new file mode 100644 index 00000000..df961cae Binary files /dev/null and b/translated_images/iot-hub-direct-method-request.86a5026e91f4ca1864e2043fab4b8199e42c2c6efc1209973cb56f199646b171.es.png differ diff --git a/translated_images/iot-hub-direct-method-request.86a5026e91f4ca1864e2043fab4b8199e42c2c6efc1209973cb56f199646b171.hk.png b/translated_images/iot-hub-direct-method-request.86a5026e91f4ca1864e2043fab4b8199e42c2c6efc1209973cb56f199646b171.hk.png new file mode 100644 index 00000000..df961cae Binary files /dev/null and b/translated_images/iot-hub-direct-method-request.86a5026e91f4ca1864e2043fab4b8199e42c2c6efc1209973cb56f199646b171.hk.png differ diff --git a/translated_images/iot-messages-to-serverless.0194da1cc0732bb7d0f823aed3fce54735c6b1ad3bf36089804d8aaefc0a774f.es.png b/translated_images/iot-messages-to-serverless.0194da1cc0732bb7d0f823aed3fce54735c6b1ad3bf36089804d8aaefc0a774f.es.png new file mode 100644 index 00000000..aaeaeff8 Binary files /dev/null and b/translated_images/iot-messages-to-serverless.0194da1cc0732bb7d0f823aed3fce54735c6b1ad3bf36089804d8aaefc0a774f.es.png differ diff --git a/translated_images/iot-messages-to-serverless.0194da1cc0732bb7d0f823aed3fce54735c6b1ad3bf36089804d8aaefc0a774f.hk.png b/translated_images/iot-messages-to-serverless.0194da1cc0732bb7d0f823aed3fce54735c6b1ad3bf36089804d8aaefc0a774f.hk.png new file mode 100644 index 00000000..aaeaeff8 Binary files /dev/null and b/translated_images/iot-messages-to-serverless.0194da1cc0732bb7d0f823aed3fce54735c6b1ad3bf36089804d8aaefc0a774f.hk.png differ diff --git a/translated_images/iot-reference-architecture-azure.0b8d2161af924cb18ae48a8558a19541cca47f27264851b5b7e56d7b8bb372ac.es.png b/translated_images/iot-reference-architecture-azure.0b8d2161af924cb18ae48a8558a19541cca47f27264851b5b7e56d7b8bb372ac.es.png new file mode 100644 index 00000000..7613fe86 Binary files /dev/null and b/translated_images/iot-reference-architecture-azure.0b8d2161af924cb18ae48a8558a19541cca47f27264851b5b7e56d7b8bb372ac.es.png differ diff --git a/translated_images/iot-reference-architecture-azure.0b8d2161af924cb18ae48a8558a19541cca47f27264851b5b7e56d7b8bb372ac.hk.png b/translated_images/iot-reference-architecture-azure.0b8d2161af924cb18ae48a8558a19541cca47f27264851b5b7e56d7b8bb372ac.hk.png new file mode 100644 index 00000000..7613fe86 Binary files /dev/null and b/translated_images/iot-reference-architecture-azure.0b8d2161af924cb18ae48a8558a19541cca47f27264851b5b7e56d7b8bb372ac.hk.png differ diff --git a/translated_images/iot-reference-architecture-fruit-quality.cc705f121c3b6fa71c800d9630935ac34bc08223a04601e35f41d5e9b5dd5207.es.png b/translated_images/iot-reference-architecture-fruit-quality.cc705f121c3b6fa71c800d9630935ac34bc08223a04601e35f41d5e9b5dd5207.es.png new file mode 100644 index 00000000..335bdf32 Binary files /dev/null and b/translated_images/iot-reference-architecture-fruit-quality.cc705f121c3b6fa71c800d9630935ac34bc08223a04601e35f41d5e9b5dd5207.es.png differ diff --git a/translated_images/iot-reference-architecture-fruit-quality.cc705f121c3b6fa71c800d9630935ac34bc08223a04601e35f41d5e9b5dd5207.hk.png b/translated_images/iot-reference-architecture-fruit-quality.cc705f121c3b6fa71c800d9630935ac34bc08223a04601e35f41d5e9b5dd5207.hk.png new file mode 100644 index 00000000..335bdf32 Binary files /dev/null and b/translated_images/iot-reference-architecture-fruit-quality.cc705f121c3b6fa71c800d9630935ac34bc08223a04601e35f41d5e9b5dd5207.hk.png differ diff --git a/translated_images/iot-reference-architecture.2278b98b55c6d4e89bde18eada3688d893861d43507641804dd2f9d3079cfaa0.es.png b/translated_images/iot-reference-architecture.2278b98b55c6d4e89bde18eada3688d893861d43507641804dd2f9d3079cfaa0.es.png new file mode 100644 index 00000000..32c8ba10 Binary files /dev/null and b/translated_images/iot-reference-architecture.2278b98b55c6d4e89bde18eada3688d893861d43507641804dd2f9d3079cfaa0.es.png differ diff --git a/translated_images/iot-reference-architecture.2278b98b55c6d4e89bde18eada3688d893861d43507641804dd2f9d3079cfaa0.hk.png b/translated_images/iot-reference-architecture.2278b98b55c6d4e89bde18eada3688d893861d43507641804dd2f9d3079cfaa0.hk.png new file mode 100644 index 00000000..32c8ba10 Binary files /dev/null and b/translated_images/iot-reference-architecture.2278b98b55c6d4e89bde18eada3688d893861d43507641804dd2f9d3079cfaa0.hk.png differ diff --git a/translated_images/iot-service-allowed-denied-connection.818b0063ac213fb84204a7229303764d9b467ca430fb822b4ac2fca267d56726.es.png b/translated_images/iot-service-allowed-denied-connection.818b0063ac213fb84204a7229303764d9b467ca430fb822b4ac2fca267d56726.es.png new file mode 100644 index 00000000..82802e17 Binary files /dev/null and b/translated_images/iot-service-allowed-denied-connection.818b0063ac213fb84204a7229303764d9b467ca430fb822b4ac2fca267d56726.es.png differ diff --git a/translated_images/iot-service-allowed-denied-connection.818b0063ac213fb84204a7229303764d9b467ca430fb822b4ac2fca267d56726.hk.png b/translated_images/iot-service-allowed-denied-connection.818b0063ac213fb84204a7229303764d9b467ca430fb822b4ac2fca267d56726.hk.png new file mode 100644 index 00000000..82802e17 Binary files /dev/null and b/translated_images/iot-service-allowed-denied-connection.818b0063ac213fb84204a7229303764d9b467ca430fb822b4ac2fca267d56726.hk.png differ diff --git a/translated_images/iot-service-connectivity.7e873847921a5d6fd60d0ba3a943210194518cee0d4e362476624316443275c3.es.png b/translated_images/iot-service-connectivity.7e873847921a5d6fd60d0ba3a943210194518cee0d4e362476624316443275c3.es.png new file mode 100644 index 00000000..8214fc2c Binary files /dev/null and b/translated_images/iot-service-connectivity.7e873847921a5d6fd60d0ba3a943210194518cee0d4e362476624316443275c3.es.png differ diff --git a/translated_images/iot-service-connectivity.7e873847921a5d6fd60d0ba3a943210194518cee0d4e362476624316443275c3.hk.png b/translated_images/iot-service-connectivity.7e873847921a5d6fd60d0ba3a943210194518cee0d4e362476624316443275c3.hk.png new file mode 100644 index 00000000..8214fc2c Binary files /dev/null and b/translated_images/iot-service-connectivity.7e873847921a5d6fd60d0ba3a943210194518cee0d4e362476624316443275c3.hk.png differ diff --git a/translated_images/latitude-equator.feccc3214b7d9fb1e1b2e44f938081c85149f092152de1509783b344e5f2097a.es.png b/translated_images/latitude-equator.feccc3214b7d9fb1e1b2e44f938081c85149f092152de1509783b344e5f2097a.es.png new file mode 100644 index 00000000..434baaad Binary files /dev/null and b/translated_images/latitude-equator.feccc3214b7d9fb1e1b2e44f938081c85149f092152de1509783b344e5f2097a.es.png differ diff --git a/translated_images/latitude-equator.feccc3214b7d9fb1e1b2e44f938081c85149f092152de1509783b344e5f2097a.hk.png b/translated_images/latitude-equator.feccc3214b7d9fb1e1b2e44f938081c85149f092152de1509783b344e5f2097a.hk.png new file mode 100644 index 00000000..434baaad Binary files /dev/null and b/translated_images/latitude-equator.feccc3214b7d9fb1e1b2e44f938081c85149f092152de1509783b344e5f2097a.hk.png differ diff --git a/translated_images/latitude-lines.11d8d91dfb2014a57437272d7db7fd6607243098e8685f06e0c5f1ec984cb7eb.es.png b/translated_images/latitude-lines.11d8d91dfb2014a57437272d7db7fd6607243098e8685f06e0c5f1ec984cb7eb.es.png new file mode 100644 index 00000000..d32271b5 Binary files /dev/null and b/translated_images/latitude-lines.11d8d91dfb2014a57437272d7db7fd6607243098e8685f06e0c5f1ec984cb7eb.es.png differ diff --git a/translated_images/latitude-lines.11d8d91dfb2014a57437272d7db7fd6607243098e8685f06e0c5f1ec984cb7eb.hk.png b/translated_images/latitude-lines.11d8d91dfb2014a57437272d7db7fd6607243098e8685f06e0c5f1ec984cb7eb.hk.png new file mode 100644 index 00000000..d32271b5 Binary files /dev/null and b/translated_images/latitude-lines.11d8d91dfb2014a57437272d7db7fd6607243098e8685f06e0c5f1ec984cb7eb.hk.png differ diff --git a/translated_images/led-digital-control.13b9be14077ea49f883c2ec52e1ce1c587804f2ed653f4061661e6a8783dd8c7.es.png b/translated_images/led-digital-control.13b9be14077ea49f883c2ec52e1ce1c587804f2ed653f4061661e6a8783dd8c7.es.png new file mode 100644 index 00000000..04cd7dc8 Binary files /dev/null and b/translated_images/led-digital-control.13b9be14077ea49f883c2ec52e1ce1c587804f2ed653f4061661e6a8783dd8c7.es.png differ diff --git a/translated_images/led-digital-control.13b9be14077ea49f883c2ec52e1ce1c587804f2ed653f4061661e6a8783dd8c7.hk.png b/translated_images/led-digital-control.13b9be14077ea49f883c2ec52e1ce1c587804f2ed653f4061661e6a8783dd8c7.hk.png new file mode 100644 index 00000000..04cd7dc8 Binary files /dev/null and b/translated_images/led-digital-control.13b9be14077ea49f883c2ec52e1ce1c587804f2ed653f4061661e6a8783dd8c7.hk.png differ diff --git a/translated_images/led.ec6d94f66676a174ad06d9fa9ea49c2ee89beb18b312d5c6476467c66375b07f.es.png b/translated_images/led.ec6d94f66676a174ad06d9fa9ea49c2ee89beb18b312d5c6476467c66375b07f.es.png new file mode 100644 index 00000000..a8a12bce Binary files /dev/null and b/translated_images/led.ec6d94f66676a174ad06d9fa9ea49c2ee89beb18b312d5c6476467c66375b07f.es.png differ diff --git a/translated_images/led.ec6d94f66676a174ad06d9fa9ea49c2ee89beb18b312d5c6476467c66375b07f.hk.png b/translated_images/led.ec6d94f66676a174ad06d9fa9ea49c2ee89beb18b312d5c6476467c66375b07f.hk.png new file mode 100644 index 00000000..a8a12bce Binary files /dev/null and b/translated_images/led.ec6d94f66676a174ad06d9fa9ea49c2ee89beb18b312d5c6476467c66375b07f.hk.png differ diff --git a/translated_images/lesson-1.2606670fa61ee904687da5d6fa4e726639d524d064c895117da1b95b9ff6251d.es.jpg b/translated_images/lesson-1.2606670fa61ee904687da5d6fa4e726639d524d064c895117da1b95b9ff6251d.es.jpg new file mode 100644 index 00000000..23ea98b2 Binary files /dev/null and b/translated_images/lesson-1.2606670fa61ee904687da5d6fa4e726639d524d064c895117da1b95b9ff6251d.es.jpg differ diff --git a/translated_images/lesson-1.2606670fa61ee904687da5d6fa4e726639d524d064c895117da1b95b9ff6251d.hk.jpg b/translated_images/lesson-1.2606670fa61ee904687da5d6fa4e726639d524d064c895117da1b95b9ff6251d.hk.jpg new file mode 100644 index 00000000..23ea98b2 Binary files /dev/null and b/translated_images/lesson-1.2606670fa61ee904687da5d6fa4e726639d524d064c895117da1b95b9ff6251d.hk.jpg differ diff --git a/translated_images/lesson-10.829c86b80b9403bb770929ee553a1d293afe50dc23121aaf9be144673ae012cc.es.jpg b/translated_images/lesson-10.829c86b80b9403bb770929ee553a1d293afe50dc23121aaf9be144673ae012cc.es.jpg new file mode 100644 index 00000000..1e3581d3 Binary files /dev/null and b/translated_images/lesson-10.829c86b80b9403bb770929ee553a1d293afe50dc23121aaf9be144673ae012cc.es.jpg differ diff --git a/translated_images/lesson-10.829c86b80b9403bb770929ee553a1d293afe50dc23121aaf9be144673ae012cc.hk.jpg b/translated_images/lesson-10.829c86b80b9403bb770929ee553a1d293afe50dc23121aaf9be144673ae012cc.hk.jpg new file mode 100644 index 00000000..1e3581d3 Binary files /dev/null and b/translated_images/lesson-10.829c86b80b9403bb770929ee553a1d293afe50dc23121aaf9be144673ae012cc.hk.jpg differ diff --git a/translated_images/lesson-11.9fddbac4b664c6d50ab7ac9bb32f1fc3f945f03760e72f7f43938073762fb017.es.jpg b/translated_images/lesson-11.9fddbac4b664c6d50ab7ac9bb32f1fc3f945f03760e72f7f43938073762fb017.es.jpg new file mode 100644 index 00000000..554ea37b Binary files /dev/null and b/translated_images/lesson-11.9fddbac4b664c6d50ab7ac9bb32f1fc3f945f03760e72f7f43938073762fb017.es.jpg differ diff --git a/translated_images/lesson-11.9fddbac4b664c6d50ab7ac9bb32f1fc3f945f03760e72f7f43938073762fb017.hk.jpg b/translated_images/lesson-11.9fddbac4b664c6d50ab7ac9bb32f1fc3f945f03760e72f7f43938073762fb017.hk.jpg new file mode 100644 index 00000000..554ea37b Binary files /dev/null and b/translated_images/lesson-11.9fddbac4b664c6d50ab7ac9bb32f1fc3f945f03760e72f7f43938073762fb017.hk.jpg differ diff --git a/translated_images/lesson-12.ca7f53039712a3ec14ad6474d8445361c84adab643edc53fa6269b77895606bb.es.jpg b/translated_images/lesson-12.ca7f53039712a3ec14ad6474d8445361c84adab643edc53fa6269b77895606bb.es.jpg new file mode 100644 index 00000000..427ba4c3 Binary files /dev/null and b/translated_images/lesson-12.ca7f53039712a3ec14ad6474d8445361c84adab643edc53fa6269b77895606bb.es.jpg differ diff --git a/translated_images/lesson-12.ca7f53039712a3ec14ad6474d8445361c84adab643edc53fa6269b77895606bb.hk.jpg b/translated_images/lesson-12.ca7f53039712a3ec14ad6474d8445361c84adab643edc53fa6269b77895606bb.hk.jpg new file mode 100644 index 00000000..427ba4c3 Binary files /dev/null and b/translated_images/lesson-12.ca7f53039712a3ec14ad6474d8445361c84adab643edc53fa6269b77895606bb.hk.jpg differ diff --git a/translated_images/lesson-13.a259db1485021be7d7c72e90842fbe0ab977529e8684c179b5fb1ea75e92b3ef.es.jpg b/translated_images/lesson-13.a259db1485021be7d7c72e90842fbe0ab977529e8684c179b5fb1ea75e92b3ef.es.jpg new file mode 100644 index 00000000..b2357285 Binary files /dev/null and b/translated_images/lesson-13.a259db1485021be7d7c72e90842fbe0ab977529e8684c179b5fb1ea75e92b3ef.es.jpg differ diff --git a/translated_images/lesson-13.a259db1485021be7d7c72e90842fbe0ab977529e8684c179b5fb1ea75e92b3ef.hk.jpg b/translated_images/lesson-13.a259db1485021be7d7c72e90842fbe0ab977529e8684c179b5fb1ea75e92b3ef.hk.jpg new file mode 100644 index 00000000..b2357285 Binary files /dev/null and b/translated_images/lesson-13.a259db1485021be7d7c72e90842fbe0ab977529e8684c179b5fb1ea75e92b3ef.hk.jpg differ diff --git a/translated_images/lesson-14.63980c5150ae3c153e770fb71d044c1845dce79248d86bed9fc525adf3ede73c.es.jpg b/translated_images/lesson-14.63980c5150ae3c153e770fb71d044c1845dce79248d86bed9fc525adf3ede73c.es.jpg new file mode 100644 index 00000000..1736ebb4 Binary files /dev/null and b/translated_images/lesson-14.63980c5150ae3c153e770fb71d044c1845dce79248d86bed9fc525adf3ede73c.es.jpg differ diff --git a/translated_images/lesson-14.63980c5150ae3c153e770fb71d044c1845dce79248d86bed9fc525adf3ede73c.hk.jpg b/translated_images/lesson-14.63980c5150ae3c153e770fb71d044c1845dce79248d86bed9fc525adf3ede73c.hk.jpg new file mode 100644 index 00000000..1736ebb4 Binary files /dev/null and b/translated_images/lesson-14.63980c5150ae3c153e770fb71d044c1845dce79248d86bed9fc525adf3ede73c.hk.jpg differ diff --git a/translated_images/lesson-15.843d21afdc6fb2bba70cd9db7b7d2f91598859fafda2078b0bdc44954194b6c0.es.jpg b/translated_images/lesson-15.843d21afdc6fb2bba70cd9db7b7d2f91598859fafda2078b0bdc44954194b6c0.es.jpg new file mode 100644 index 00000000..bf1d724f Binary files /dev/null and b/translated_images/lesson-15.843d21afdc6fb2bba70cd9db7b7d2f91598859fafda2078b0bdc44954194b6c0.es.jpg differ diff --git a/translated_images/lesson-15.843d21afdc6fb2bba70cd9db7b7d2f91598859fafda2078b0bdc44954194b6c0.hk.jpg b/translated_images/lesson-15.843d21afdc6fb2bba70cd9db7b7d2f91598859fafda2078b0bdc44954194b6c0.hk.jpg new file mode 100644 index 00000000..bf1d724f Binary files /dev/null and b/translated_images/lesson-15.843d21afdc6fb2bba70cd9db7b7d2f91598859fafda2078b0bdc44954194b6c0.hk.jpg differ diff --git a/translated_images/lesson-16.215daf18b00631fbdfd64c6fc2dc6044dff5d544288825d8076f9fb83d964c23.es.jpg b/translated_images/lesson-16.215daf18b00631fbdfd64c6fc2dc6044dff5d544288825d8076f9fb83d964c23.es.jpg new file mode 100644 index 00000000..bb78259a Binary files /dev/null and b/translated_images/lesson-16.215daf18b00631fbdfd64c6fc2dc6044dff5d544288825d8076f9fb83d964c23.es.jpg differ diff --git a/translated_images/lesson-16.215daf18b00631fbdfd64c6fc2dc6044dff5d544288825d8076f9fb83d964c23.hk.jpg b/translated_images/lesson-16.215daf18b00631fbdfd64c6fc2dc6044dff5d544288825d8076f9fb83d964c23.hk.jpg new file mode 100644 index 00000000..bb78259a Binary files /dev/null and b/translated_images/lesson-16.215daf18b00631fbdfd64c6fc2dc6044dff5d544288825d8076f9fb83d964c23.hk.jpg differ diff --git a/translated_images/lesson-17.bc333c3c35ba8e42cce666cfffa82b915f787f455bd94e006aea2b6f2722421a.es.jpg b/translated_images/lesson-17.bc333c3c35ba8e42cce666cfffa82b915f787f455bd94e006aea2b6f2722421a.es.jpg new file mode 100644 index 00000000..b311b568 Binary files /dev/null and b/translated_images/lesson-17.bc333c3c35ba8e42cce666cfffa82b915f787f455bd94e006aea2b6f2722421a.es.jpg differ diff --git a/translated_images/lesson-17.bc333c3c35ba8e42cce666cfffa82b915f787f455bd94e006aea2b6f2722421a.hk.jpg b/translated_images/lesson-17.bc333c3c35ba8e42cce666cfffa82b915f787f455bd94e006aea2b6f2722421a.hk.jpg new file mode 100644 index 00000000..b311b568 Binary files /dev/null and b/translated_images/lesson-17.bc333c3c35ba8e42cce666cfffa82b915f787f455bd94e006aea2b6f2722421a.hk.jpg differ diff --git a/translated_images/lesson-18.92c32ed1d354caa5a54baa4032cf0b172d4655e8e326ad5d46c558a0def15365.es.jpg b/translated_images/lesson-18.92c32ed1d354caa5a54baa4032cf0b172d4655e8e326ad5d46c558a0def15365.es.jpg new file mode 100644 index 00000000..5bd350fd Binary files /dev/null and b/translated_images/lesson-18.92c32ed1d354caa5a54baa4032cf0b172d4655e8e326ad5d46c558a0def15365.es.jpg differ diff --git a/translated_images/lesson-18.92c32ed1d354caa5a54baa4032cf0b172d4655e8e326ad5d46c558a0def15365.hk.jpg b/translated_images/lesson-18.92c32ed1d354caa5a54baa4032cf0b172d4655e8e326ad5d46c558a0def15365.hk.jpg new file mode 100644 index 00000000..5bd350fd Binary files /dev/null and b/translated_images/lesson-18.92c32ed1d354caa5a54baa4032cf0b172d4655e8e326ad5d46c558a0def15365.hk.jpg differ diff --git a/translated_images/lesson-19.cf6973cecadf080c4b526310620dc4d6f5994c80fb0139c6f378cc9ca2d435cd.es.jpg b/translated_images/lesson-19.cf6973cecadf080c4b526310620dc4d6f5994c80fb0139c6f378cc9ca2d435cd.es.jpg new file mode 100644 index 00000000..66fbe114 Binary files /dev/null and b/translated_images/lesson-19.cf6973cecadf080c4b526310620dc4d6f5994c80fb0139c6f378cc9ca2d435cd.es.jpg differ diff --git a/translated_images/lesson-19.cf6973cecadf080c4b526310620dc4d6f5994c80fb0139c6f378cc9ca2d435cd.hk.jpg b/translated_images/lesson-19.cf6973cecadf080c4b526310620dc4d6f5994c80fb0139c6f378cc9ca2d435cd.hk.jpg new file mode 100644 index 00000000..66fbe114 Binary files /dev/null and b/translated_images/lesson-19.cf6973cecadf080c4b526310620dc4d6f5994c80fb0139c6f378cc9ca2d435cd.hk.jpg differ diff --git a/translated_images/lesson-2.324b0580d620c25e0a24fb7fddfc0b29a846dd4b82c08e7a9466d580ee78ce51.es.jpg b/translated_images/lesson-2.324b0580d620c25e0a24fb7fddfc0b29a846dd4b82c08e7a9466d580ee78ce51.es.jpg new file mode 100644 index 00000000..050e7206 Binary files /dev/null and b/translated_images/lesson-2.324b0580d620c25e0a24fb7fddfc0b29a846dd4b82c08e7a9466d580ee78ce51.es.jpg differ diff --git a/translated_images/lesson-2.324b0580d620c25e0a24fb7fddfc0b29a846dd4b82c08e7a9466d580ee78ce51.hk.jpg b/translated_images/lesson-2.324b0580d620c25e0a24fb7fddfc0b29a846dd4b82c08e7a9466d580ee78ce51.hk.jpg new file mode 100644 index 00000000..050e7206 Binary files /dev/null and b/translated_images/lesson-2.324b0580d620c25e0a24fb7fddfc0b29a846dd4b82c08e7a9466d580ee78ce51.hk.jpg differ diff --git a/translated_images/lesson-20.0211df9551a8abb300fc8fcf7dc2789468dea2eabe9202273ac077b0ba37f15e.es.jpg b/translated_images/lesson-20.0211df9551a8abb300fc8fcf7dc2789468dea2eabe9202273ac077b0ba37f15e.es.jpg new file mode 100644 index 00000000..91c64faa Binary files /dev/null and b/translated_images/lesson-20.0211df9551a8abb300fc8fcf7dc2789468dea2eabe9202273ac077b0ba37f15e.es.jpg differ diff --git a/translated_images/lesson-20.0211df9551a8abb300fc8fcf7dc2789468dea2eabe9202273ac077b0ba37f15e.hk.jpg b/translated_images/lesson-20.0211df9551a8abb300fc8fcf7dc2789468dea2eabe9202273ac077b0ba37f15e.hk.jpg new file mode 100644 index 00000000..91c64faa Binary files /dev/null and b/translated_images/lesson-20.0211df9551a8abb300fc8fcf7dc2789468dea2eabe9202273ac077b0ba37f15e.hk.jpg differ diff --git a/translated_images/lesson-21.e34de51354d6606fb5ee08d8c89d0222eea0a2a7aaf744a8805ae847c4f69dc4.es.jpg b/translated_images/lesson-21.e34de51354d6606fb5ee08d8c89d0222eea0a2a7aaf744a8805ae847c4f69dc4.es.jpg new file mode 100644 index 00000000..36e1a4b3 Binary files /dev/null and b/translated_images/lesson-21.e34de51354d6606fb5ee08d8c89d0222eea0a2a7aaf744a8805ae847c4f69dc4.es.jpg differ diff --git a/translated_images/lesson-21.e34de51354d6606fb5ee08d8c89d0222eea0a2a7aaf744a8805ae847c4f69dc4.hk.jpg b/translated_images/lesson-21.e34de51354d6606fb5ee08d8c89d0222eea0a2a7aaf744a8805ae847c4f69dc4.hk.jpg new file mode 100644 index 00000000..36e1a4b3 Binary files /dev/null and b/translated_images/lesson-21.e34de51354d6606fb5ee08d8c89d0222eea0a2a7aaf744a8805ae847c4f69dc4.hk.jpg differ diff --git a/translated_images/lesson-22.6148ea28500d9e00c396aaa2649935fb6641362c8f03d8e5e90a676977ab01dd.es.jpg b/translated_images/lesson-22.6148ea28500d9e00c396aaa2649935fb6641362c8f03d8e5e90a676977ab01dd.es.jpg new file mode 100644 index 00000000..1b87df4c Binary files /dev/null and b/translated_images/lesson-22.6148ea28500d9e00c396aaa2649935fb6641362c8f03d8e5e90a676977ab01dd.es.jpg differ diff --git a/translated_images/lesson-22.6148ea28500d9e00c396aaa2649935fb6641362c8f03d8e5e90a676977ab01dd.hk.jpg b/translated_images/lesson-22.6148ea28500d9e00c396aaa2649935fb6641362c8f03d8e5e90a676977ab01dd.hk.jpg new file mode 100644 index 00000000..1b87df4c Binary files /dev/null and b/translated_images/lesson-22.6148ea28500d9e00c396aaa2649935fb6641362c8f03d8e5e90a676977ab01dd.hk.jpg differ diff --git a/translated_images/lesson-23.f38483e1d4df4828990d3f02d60e46c978b075d384ae7cb4f7bab738e107c850.es.jpg b/translated_images/lesson-23.f38483e1d4df4828990d3f02d60e46c978b075d384ae7cb4f7bab738e107c850.es.jpg new file mode 100644 index 00000000..8df37a22 Binary files /dev/null and b/translated_images/lesson-23.f38483e1d4df4828990d3f02d60e46c978b075d384ae7cb4f7bab738e107c850.es.jpg differ diff --git a/translated_images/lesson-23.f38483e1d4df4828990d3f02d60e46c978b075d384ae7cb4f7bab738e107c850.hk.jpg b/translated_images/lesson-23.f38483e1d4df4828990d3f02d60e46c978b075d384ae7cb4f7bab738e107c850.hk.jpg new file mode 100644 index 00000000..8df37a22 Binary files /dev/null and b/translated_images/lesson-23.f38483e1d4df4828990d3f02d60e46c978b075d384ae7cb4f7bab738e107c850.hk.jpg differ diff --git a/translated_images/lesson-24.4246968ed058510ab275052e87ef9aa89c7b2f938915d103c605c04dc6cd5bb7.es.jpg b/translated_images/lesson-24.4246968ed058510ab275052e87ef9aa89c7b2f938915d103c605c04dc6cd5bb7.es.jpg new file mode 100644 index 00000000..943af1b9 Binary files /dev/null and b/translated_images/lesson-24.4246968ed058510ab275052e87ef9aa89c7b2f938915d103c605c04dc6cd5bb7.es.jpg differ diff --git a/translated_images/lesson-24.4246968ed058510ab275052e87ef9aa89c7b2f938915d103c605c04dc6cd5bb7.hk.jpg b/translated_images/lesson-24.4246968ed058510ab275052e87ef9aa89c7b2f938915d103c605c04dc6cd5bb7.hk.jpg new file mode 100644 index 00000000..943af1b9 Binary files /dev/null and b/translated_images/lesson-24.4246968ed058510ab275052e87ef9aa89c7b2f938915d103c605c04dc6cd5bb7.hk.jpg differ diff --git a/translated_images/lesson-3.cc3b7b4cd646de598698cce043c0393fd62ef42bac2eaf60e61272cd844250f4.es.jpg b/translated_images/lesson-3.cc3b7b4cd646de598698cce043c0393fd62ef42bac2eaf60e61272cd844250f4.es.jpg new file mode 100644 index 00000000..5a96f7fb Binary files /dev/null and b/translated_images/lesson-3.cc3b7b4cd646de598698cce043c0393fd62ef42bac2eaf60e61272cd844250f4.es.jpg differ diff --git a/translated_images/lesson-3.cc3b7b4cd646de598698cce043c0393fd62ef42bac2eaf60e61272cd844250f4.hk.jpg b/translated_images/lesson-3.cc3b7b4cd646de598698cce043c0393fd62ef42bac2eaf60e61272cd844250f4.hk.jpg new file mode 100644 index 00000000..5a96f7fb Binary files /dev/null and b/translated_images/lesson-3.cc3b7b4cd646de598698cce043c0393fd62ef42bac2eaf60e61272cd844250f4.hk.jpg differ diff --git a/translated_images/lesson-4.7344e074ea68fa545fd320b12dce36d72dd62d28c3b4596cb26cf315f434b98f.es.jpg b/translated_images/lesson-4.7344e074ea68fa545fd320b12dce36d72dd62d28c3b4596cb26cf315f434b98f.es.jpg new file mode 100644 index 00000000..8f0bee50 Binary files /dev/null and b/translated_images/lesson-4.7344e074ea68fa545fd320b12dce36d72dd62d28c3b4596cb26cf315f434b98f.es.jpg differ diff --git a/translated_images/lesson-4.7344e074ea68fa545fd320b12dce36d72dd62d28c3b4596cb26cf315f434b98f.hk.jpg b/translated_images/lesson-4.7344e074ea68fa545fd320b12dce36d72dd62d28c3b4596cb26cf315f434b98f.hk.jpg new file mode 100644 index 00000000..8f0bee50 Binary files /dev/null and b/translated_images/lesson-4.7344e074ea68fa545fd320b12dce36d72dd62d28c3b4596cb26cf315f434b98f.hk.jpg differ diff --git a/translated_images/lesson-5.42b234299279d263143148b88ab4583861a32ddb03110c6c1120e41bb88b2592.es.jpg b/translated_images/lesson-5.42b234299279d263143148b88ab4583861a32ddb03110c6c1120e41bb88b2592.es.jpg new file mode 100644 index 00000000..4ba24109 Binary files /dev/null and b/translated_images/lesson-5.42b234299279d263143148b88ab4583861a32ddb03110c6c1120e41bb88b2592.es.jpg differ diff --git a/translated_images/lesson-5.42b234299279d263143148b88ab4583861a32ddb03110c6c1120e41bb88b2592.hk.jpg b/translated_images/lesson-5.42b234299279d263143148b88ab4583861a32ddb03110c6c1120e41bb88b2592.hk.jpg new file mode 100644 index 00000000..4ba24109 Binary files /dev/null and b/translated_images/lesson-5.42b234299279d263143148b88ab4583861a32ddb03110c6c1120e41bb88b2592.hk.jpg differ diff --git a/translated_images/lesson-6.3e493b60eee85adc8c74dfeaaec3a3a6cfba61fedbcb84aa0146e7e80603a5dd.es.jpg b/translated_images/lesson-6.3e493b60eee85adc8c74dfeaaec3a3a6cfba61fedbcb84aa0146e7e80603a5dd.es.jpg new file mode 100644 index 00000000..cdf0f557 Binary files /dev/null and b/translated_images/lesson-6.3e493b60eee85adc8c74dfeaaec3a3a6cfba61fedbcb84aa0146e7e80603a5dd.es.jpg differ diff --git a/translated_images/lesson-6.3e493b60eee85adc8c74dfeaaec3a3a6cfba61fedbcb84aa0146e7e80603a5dd.hk.jpg b/translated_images/lesson-6.3e493b60eee85adc8c74dfeaaec3a3a6cfba61fedbcb84aa0146e7e80603a5dd.hk.jpg new file mode 100644 index 00000000..cdf0f557 Binary files /dev/null and b/translated_images/lesson-6.3e493b60eee85adc8c74dfeaaec3a3a6cfba61fedbcb84aa0146e7e80603a5dd.hk.jpg differ diff --git a/translated_images/lesson-7.30b5f577d3cb8e031238751475cb519c7d6dbaea261b5df4643d086ffb2a03bb.es.jpg b/translated_images/lesson-7.30b5f577d3cb8e031238751475cb519c7d6dbaea261b5df4643d086ffb2a03bb.es.jpg new file mode 100644 index 00000000..f59ee98d Binary files /dev/null and b/translated_images/lesson-7.30b5f577d3cb8e031238751475cb519c7d6dbaea261b5df4643d086ffb2a03bb.es.jpg differ diff --git a/translated_images/lesson-7.30b5f577d3cb8e031238751475cb519c7d6dbaea261b5df4643d086ffb2a03bb.hk.jpg b/translated_images/lesson-7.30b5f577d3cb8e031238751475cb519c7d6dbaea261b5df4643d086ffb2a03bb.hk.jpg new file mode 100644 index 00000000..f59ee98d Binary files /dev/null and b/translated_images/lesson-7.30b5f577d3cb8e031238751475cb519c7d6dbaea261b5df4643d086ffb2a03bb.hk.jpg differ diff --git a/translated_images/lesson-8.3f21f3c11159e6a0a376351973ea5724d5de68fa23b4288853a174bed9ac48c3.es.jpg b/translated_images/lesson-8.3f21f3c11159e6a0a376351973ea5724d5de68fa23b4288853a174bed9ac48c3.es.jpg new file mode 100644 index 00000000..5bdbfd14 Binary files /dev/null and b/translated_images/lesson-8.3f21f3c11159e6a0a376351973ea5724d5de68fa23b4288853a174bed9ac48c3.es.jpg differ diff --git a/translated_images/lesson-8.3f21f3c11159e6a0a376351973ea5724d5de68fa23b4288853a174bed9ac48c3.hk.jpg b/translated_images/lesson-8.3f21f3c11159e6a0a376351973ea5724d5de68fa23b4288853a174bed9ac48c3.hk.jpg new file mode 100644 index 00000000..5bdbfd14 Binary files /dev/null and b/translated_images/lesson-8.3f21f3c11159e6a0a376351973ea5724d5de68fa23b4288853a174bed9ac48c3.hk.jpg differ diff --git a/translated_images/lesson-9.dfe99c8e891f48e179724520da9f5794392cf9a625079281ccdcbf09bd85e1b6.es.jpg b/translated_images/lesson-9.dfe99c8e891f48e179724520da9f5794392cf9a625079281ccdcbf09bd85e1b6.es.jpg new file mode 100644 index 00000000..b78ab3ac Binary files /dev/null and b/translated_images/lesson-9.dfe99c8e891f48e179724520da9f5794392cf9a625079281ccdcbf09bd85e1b6.es.jpg differ diff --git a/translated_images/lesson-9.dfe99c8e891f48e179724520da9f5794392cf9a625079281ccdcbf09bd85e1b6.hk.jpg b/translated_images/lesson-9.dfe99c8e891f48e179724520da9f5794392cf9a625079281ccdcbf09bd85e1b6.hk.jpg new file mode 100644 index 00000000..b78ab3ac Binary files /dev/null and b/translated_images/lesson-9.dfe99c8e891f48e179724520da9f5794392cf9a625079281ccdcbf09bd85e1b6.hk.jpg differ diff --git a/translated_images/light-switch.760317ad6ab8bd6d611da5352dfe9c73a94a0822ccec7df3c8bae35da18e1658.es.png b/translated_images/light-switch.760317ad6ab8bd6d611da5352dfe9c73a94a0822ccec7df3c8bae35da18e1658.es.png new file mode 100644 index 00000000..d071dffe Binary files /dev/null and b/translated_images/light-switch.760317ad6ab8bd6d611da5352dfe9c73a94a0822ccec7df3c8bae35da18e1658.es.png differ diff --git a/translated_images/light-switch.760317ad6ab8bd6d611da5352dfe9c73a94a0822ccec7df3c8bae35da18e1658.hk.png b/translated_images/light-switch.760317ad6ab8bd6d611da5352dfe9c73a94a0822ccec7df3c8bae35da18e1658.hk.png new file mode 100644 index 00000000..d071dffe Binary files /dev/null and b/translated_images/light-switch.760317ad6ab8bd6d611da5352dfe9c73a94a0822ccec7df3c8bae35da18e1658.hk.png differ diff --git a/translated_images/lines-of-longitude-and-latitude.032aca9d3e402c4e89da3f1c269b955f0dac443ae4ae3dd6e1dada5761c39a92.es.png b/translated_images/lines-of-longitude-and-latitude.032aca9d3e402c4e89da3f1c269b955f0dac443ae4ae3dd6e1dada5761c39a92.es.png new file mode 100644 index 00000000..b8947f6d Binary files /dev/null and b/translated_images/lines-of-longitude-and-latitude.032aca9d3e402c4e89da3f1c269b955f0dac443ae4ae3dd6e1dada5761c39a92.es.png differ diff --git a/translated_images/lines-of-longitude-and-latitude.032aca9d3e402c4e89da3f1c269b955f0dac443ae4ae3dd6e1dada5761c39a92.hk.png b/translated_images/lines-of-longitude-and-latitude.032aca9d3e402c4e89da3f1c269b955f0dac443ae4ae3dd6e1dada5761c39a92.hk.png new file mode 100644 index 00000000..b8947f6d Binary files /dev/null and b/translated_images/lines-of-longitude-and-latitude.032aca9d3e402c4e89da3f1c269b955f0dac443ae4ae3dd6e1dada5761c39a92.hk.png differ diff --git a/translated_images/longitude-meridians.ab4ef1c91c064586b0185a3c8d39e585903696c6a7d28c098a93a629cddb5d20.es.png b/translated_images/longitude-meridians.ab4ef1c91c064586b0185a3c8d39e585903696c6a7d28c098a93a629cddb5d20.es.png new file mode 100644 index 00000000..5c5dfb96 Binary files /dev/null and b/translated_images/longitude-meridians.ab4ef1c91c064586b0185a3c8d39e585903696c6a7d28c098a93a629cddb5d20.es.png differ diff --git a/translated_images/longitude-meridians.ab4ef1c91c064586b0185a3c8d39e585903696c6a7d28c098a93a629cddb5d20.hk.png b/translated_images/longitude-meridians.ab4ef1c91c064586b0185a3c8d39e585903696c6a7d28c098a93a629cddb5d20.hk.png new file mode 100644 index 00000000..5c5dfb96 Binary files /dev/null and b/translated_images/longitude-meridians.ab4ef1c91c064586b0185a3c8d39e585903696c6a7d28c098a93a629cddb5d20.hk.png differ diff --git a/translated_images/longitude-prime-meridian.33b01b41ce615f9ddf85d91b0f93bdc076cfa44bb10b17296de42e2d1ba1090e.es.png b/translated_images/longitude-prime-meridian.33b01b41ce615f9ddf85d91b0f93bdc076cfa44bb10b17296de42e2d1ba1090e.es.png new file mode 100644 index 00000000..663ad7e9 Binary files /dev/null and b/translated_images/longitude-prime-meridian.33b01b41ce615f9ddf85d91b0f93bdc076cfa44bb10b17296de42e2d1ba1090e.es.png differ diff --git a/translated_images/longitude-prime-meridian.33b01b41ce615f9ddf85d91b0f93bdc076cfa44bb10b17296de42e2d1ba1090e.hk.png b/translated_images/longitude-prime-meridian.33b01b41ce615f9ddf85d91b0f93bdc076cfa44bb10b17296de42e2d1ba1090e.hk.png new file mode 100644 index 00000000..663ad7e9 Binary files /dev/null and b/translated_images/longitude-prime-meridian.33b01b41ce615f9ddf85d91b0f93bdc076cfa44bb10b17296de42e2d1ba1090e.hk.png differ diff --git a/translated_images/luis-intent-examples.25716580b2d2723cf1bafdf277d015c7f046d8cfa20f27bddf3a0873ec45fab7.es.png b/translated_images/luis-intent-examples.25716580b2d2723cf1bafdf277d015c7f046d8cfa20f27bddf3a0873ec45fab7.es.png new file mode 100644 index 00000000..b1e33d6b Binary files /dev/null and b/translated_images/luis-intent-examples.25716580b2d2723cf1bafdf277d015c7f046d8cfa20f27bddf3a0873ec45fab7.es.png differ diff --git a/translated_images/luis-intent-examples.25716580b2d2723cf1bafdf277d015c7f046d8cfa20f27bddf3a0873ec45fab7.hk.png b/translated_images/luis-intent-examples.25716580b2d2723cf1bafdf277d015c7f046d8cfa20f27bddf3a0873ec45fab7.hk.png new file mode 100644 index 00000000..b1e33d6b Binary files /dev/null and b/translated_images/luis-intent-examples.25716580b2d2723cf1bafdf277d015c7f046d8cfa20f27bddf3a0873ec45fab7.hk.png differ diff --git a/translated_images/luis-logo.5cb4f3e88c020ee6df4f614e8831f4a4b6809a7247bf52085fb48d629ef9be52.es.png b/translated_images/luis-logo.5cb4f3e88c020ee6df4f614e8831f4a4b6809a7247bf52085fb48d629ef9be52.es.png new file mode 100644 index 00000000..2a03ab78 Binary files /dev/null and b/translated_images/luis-logo.5cb4f3e88c020ee6df4f614e8831f4a4b6809a7247bf52085fb48d629ef9be52.es.png differ diff --git a/translated_images/luis-logo.5cb4f3e88c020ee6df4f614e8831f4a4b6809a7247bf52085fb48d629ef9be52.hk.png b/translated_images/luis-logo.5cb4f3e88c020ee6df4f614e8831f4a4b6809a7247bf52085fb48d629ef9be52.hk.png new file mode 100644 index 00000000..2a03ab78 Binary files /dev/null and b/translated_images/luis-logo.5cb4f3e88c020ee6df4f614e8831f4a4b6809a7247bf52085fb48d629ef9be52.hk.png differ diff --git a/translated_images/map-image.8fb2c53eb23ef39c1c0a4410a5282e879b3b452b707eb066ff04c5488d3d72b7.es.png b/translated_images/map-image.8fb2c53eb23ef39c1c0a4410a5282e879b3b452b707eb066ff04c5488d3d72b7.es.png new file mode 100644 index 00000000..02ef1351 Binary files /dev/null and b/translated_images/map-image.8fb2c53eb23ef39c1c0a4410a5282e879b3b452b707eb066ff04c5488d3d72b7.es.png differ diff --git a/translated_images/map-image.8fb2c53eb23ef39c1c0a4410a5282e879b3b452b707eb066ff04c5488d3d72b7.hk.png b/translated_images/map-image.8fb2c53eb23ef39c1c0a4410a5282e879b3b452b707eb066ff04c5488d3d72b7.hk.png new file mode 100644 index 00000000..02ef1351 Binary files /dev/null and b/translated_images/map-image.8fb2c53eb23ef39c1c0a4410a5282e879b3b452b707eb066ff04c5488d3d72b7.hk.png differ diff --git a/translated_images/map-path.896832e72dc696ffe20650e4051027d4855442d955f93fdbb80bb417ca8a406f.es.png b/translated_images/map-path.896832e72dc696ffe20650e4051027d4855442d955f93fdbb80bb417ca8a406f.es.png new file mode 100644 index 00000000..33faabd1 Binary files /dev/null and b/translated_images/map-path.896832e72dc696ffe20650e4051027d4855442d955f93fdbb80bb417ca8a406f.es.png differ diff --git a/translated_images/map-path.896832e72dc696ffe20650e4051027d4855442d955f93fdbb80bb417ca8a406f.hk.png b/translated_images/map-path.896832e72dc696ffe20650e4051027d4855442d955f93fdbb80bb417ca8a406f.hk.png new file mode 100644 index 00000000..33faabd1 Binary files /dev/null and b/translated_images/map-path.896832e72dc696ffe20650e4051027d4855442d955f93fdbb80bb417ca8a406f.hk.png differ diff --git a/translated_images/mems-microphone.80574019e1f5e4d9ee72fed720ecd25a39fc2969c91355d17ebb24ba4159e4c4.es.png b/translated_images/mems-microphone.80574019e1f5e4d9ee72fed720ecd25a39fc2969c91355d17ebb24ba4159e4c4.es.png new file mode 100644 index 00000000..aa94da2c Binary files /dev/null and b/translated_images/mems-microphone.80574019e1f5e4d9ee72fed720ecd25a39fc2969c91355d17ebb24ba4159e4c4.es.png differ diff --git a/translated_images/mems-microphone.80574019e1f5e4d9ee72fed720ecd25a39fc2969c91355d17ebb24ba4159e4c4.hk.png b/translated_images/mems-microphone.80574019e1f5e4d9ee72fed720ecd25a39fc2969c91355d17ebb24ba4159e4c4.hk.png new file mode 100644 index 00000000..aa94da2c Binary files /dev/null and b/translated_images/mems-microphone.80574019e1f5e4d9ee72fed720ecd25a39fc2969c91355d17ebb24ba4159e4c4.hk.png differ diff --git a/translated_images/microsoft-gps-location-world.a321d481b010f6adfcca139b2ba0adc53b79f58a540495b8e2ce7f779ea64bfe.es.png b/translated_images/microsoft-gps-location-world.a321d481b010f6adfcca139b2ba0adc53b79f58a540495b8e2ce7f779ea64bfe.es.png new file mode 100644 index 00000000..ac000818 Binary files /dev/null and b/translated_images/microsoft-gps-location-world.a321d481b010f6adfcca139b2ba0adc53b79f58a540495b8e2ce7f779ea64bfe.es.png differ diff --git a/translated_images/microsoft-gps-location-world.a321d481b010f6adfcca139b2ba0adc53b79f58a540495b8e2ce7f779ea64bfe.hk.png b/translated_images/microsoft-gps-location-world.a321d481b010f6adfcca139b2ba0adc53b79f58a540495b8e2ce7f779ea64bfe.hk.png new file mode 100644 index 00000000..ac000818 Binary files /dev/null and b/translated_images/microsoft-gps-location-world.a321d481b010f6adfcca139b2ba0adc53b79f58a540495b8e2ce7f779ea64bfe.hk.png differ diff --git a/translated_images/microsoft-gps-location.9eb77a13b22b7e70a0a80bd2b54c24eda141b4ee15a0373c93f8c73f4fcd81f5.es.png b/translated_images/microsoft-gps-location.9eb77a13b22b7e70a0a80bd2b54c24eda141b4ee15a0373c93f8c73f4fcd81f5.es.png new file mode 100644 index 00000000..2fb519f5 Binary files /dev/null and b/translated_images/microsoft-gps-location.9eb77a13b22b7e70a0a80bd2b54c24eda141b4ee15a0373c93f8c73f4fcd81f5.es.png differ diff --git a/translated_images/microsoft-gps-location.9eb77a13b22b7e70a0a80bd2b54c24eda141b4ee15a0373c93f8c73f4fcd81f5.hk.png b/translated_images/microsoft-gps-location.9eb77a13b22b7e70a0a80bd2b54c24eda141b4ee15a0373c93f8c73f4fcd81f5.hk.png new file mode 100644 index 00000000..2fb519f5 Binary files /dev/null and b/translated_images/microsoft-gps-location.9eb77a13b22b7e70a0a80bd2b54c24eda141b4ee15a0373c93f8c73f4fcd81f5.hk.png differ diff --git a/translated_images/mobile-controlled-thermostat.4a994010473d8d6a52ba68c67e5f02dc8928c717e93ca4b9bc55525aa75bbb60.es.png b/translated_images/mobile-controlled-thermostat.4a994010473d8d6a52ba68c67e5f02dc8928c717e93ca4b9bc55525aa75bbb60.es.png new file mode 100644 index 00000000..48459b92 Binary files /dev/null and b/translated_images/mobile-controlled-thermostat.4a994010473d8d6a52ba68c67e5f02dc8928c717e93ca4b9bc55525aa75bbb60.es.png differ diff --git a/translated_images/mobile-controlled-thermostat.4a994010473d8d6a52ba68c67e5f02dc8928c717e93ca4b9bc55525aa75bbb60.hk.png b/translated_images/mobile-controlled-thermostat.4a994010473d8d6a52ba68c67e5f02dc8928c717e93ca4b9bc55525aa75bbb60.hk.png new file mode 100644 index 00000000..48459b92 Binary files /dev/null and b/translated_images/mobile-controlled-thermostat.4a994010473d8d6a52ba68c67e5f02dc8928c717e93ca4b9bc55525aa75bbb60.hk.png differ diff --git a/translated_images/mqtt.cbf7f21d9adc3e17548b359444cc11bb4bf2010543e32ece9a47becf54438c23.es.png b/translated_images/mqtt.cbf7f21d9adc3e17548b359444cc11bb4bf2010543e32ece9a47becf54438c23.es.png new file mode 100644 index 00000000..d502a579 Binary files /dev/null and b/translated_images/mqtt.cbf7f21d9adc3e17548b359444cc11bb4bf2010543e32ece9a47becf54438c23.es.png differ diff --git a/translated_images/mqtt.cbf7f21d9adc3e17548b359444cc11bb4bf2010543e32ece9a47becf54438c23.hk.png b/translated_images/mqtt.cbf7f21d9adc3e17548b359444cc11bb4bf2010543e32ece9a47becf54438c23.hk.png new file mode 100644 index 00000000..d502a579 Binary files /dev/null and b/translated_images/mqtt.cbf7f21d9adc3e17548b359444cc11bb4bf2010543e32ece9a47becf54438c23.hk.png differ diff --git a/translated_images/noqsl-database.62d24ccf5b73f60d35c245a8533f1c7147c0928e955b82cb290b2e184bb434df.es.png b/translated_images/noqsl-database.62d24ccf5b73f60d35c245a8533f1c7147c0928e955b82cb290b2e184bb434df.es.png new file mode 100644 index 00000000..fca45002 Binary files /dev/null and b/translated_images/noqsl-database.62d24ccf5b73f60d35c245a8533f1c7147c0928e955b82cb290b2e184bb434df.es.png differ diff --git a/translated_images/noqsl-database.62d24ccf5b73f60d35c245a8533f1c7147c0928e955b82cb290b2e184bb434df.hk.png b/translated_images/noqsl-database.62d24ccf5b73f60d35c245a8533f1c7147c0928e955b82cb290b2e184bb434df.hk.png new file mode 100644 index 00000000..fca45002 Binary files /dev/null and b/translated_images/noqsl-database.62d24ccf5b73f60d35c245a8533f1c7147c0928e955b82cb290b2e184bb434df.hk.png differ diff --git a/translated_images/object-detector-cashews-tomato.1af7c26686b4db0e709754aeb196f4e73271f54e2085db3bcccb70d4a0d84d97.es.png b/translated_images/object-detector-cashews-tomato.1af7c26686b4db0e709754aeb196f4e73271f54e2085db3bcccb70d4a0d84d97.es.png new file mode 100644 index 00000000..94aa28db Binary files /dev/null and b/translated_images/object-detector-cashews-tomato.1af7c26686b4db0e709754aeb196f4e73271f54e2085db3bcccb70d4a0d84d97.es.png differ diff --git a/translated_images/object-detector-cashews-tomato.1af7c26686b4db0e709754aeb196f4e73271f54e2085db3bcccb70d4a0d84d97.hk.png b/translated_images/object-detector-cashews-tomato.1af7c26686b4db0e709754aeb196f4e73271f54e2085db3bcccb70d4a0d84d97.hk.png new file mode 100644 index 00000000..94aa28db Binary files /dev/null and b/translated_images/object-detector-cashews-tomato.1af7c26686b4db0e709754aeb196f4e73271f54e2085db3bcccb70d4a0d84d97.hk.png differ diff --git a/translated_images/object-detector-detected-tomato-paste.52656fe87af4c37b4ee540526d63e73ed075da2e54a9a060aa528e0c562fb1b6.es.png b/translated_images/object-detector-detected-tomato-paste.52656fe87af4c37b4ee540526d63e73ed075da2e54a9a060aa528e0c562fb1b6.es.png new file mode 100644 index 00000000..894df473 Binary files /dev/null and b/translated_images/object-detector-detected-tomato-paste.52656fe87af4c37b4ee540526d63e73ed075da2e54a9a060aa528e0c562fb1b6.es.png differ diff --git a/translated_images/object-detector-detected-tomato-paste.52656fe87af4c37b4ee540526d63e73ed075da2e54a9a060aa528e0c562fb1b6.hk.png b/translated_images/object-detector-detected-tomato-paste.52656fe87af4c37b4ee540526d63e73ed075da2e54a9a060aa528e0c562fb1b6.hk.png new file mode 100644 index 00000000..894df473 Binary files /dev/null and b/translated_images/object-detector-detected-tomato-paste.52656fe87af4c37b4ee540526d63e73ed075da2e54a9a060aa528e0c562fb1b6.hk.png differ diff --git a/translated_images/object-detector-tag-tomato-paste.f47c362fb0f0eb582f3bc68cf3855fb43a805106395358d41896a269c210b7b4.es.png b/translated_images/object-detector-tag-tomato-paste.f47c362fb0f0eb582f3bc68cf3855fb43a805106395358d41896a269c210b7b4.es.png new file mode 100644 index 00000000..b75dfdd2 Binary files /dev/null and b/translated_images/object-detector-tag-tomato-paste.f47c362fb0f0eb582f3bc68cf3855fb43a805106395358d41896a269c210b7b4.es.png differ diff --git a/translated_images/object-detector-tag-tomato-paste.f47c362fb0f0eb582f3bc68cf3855fb43a805106395358d41896a269c210b7b4.hk.png b/translated_images/object-detector-tag-tomato-paste.f47c362fb0f0eb582f3bc68cf3855fb43a805106395358d41896a269c210b7b4.hk.png new file mode 100644 index 00000000..b75dfdd2 Binary files /dev/null and b/translated_images/object-detector-tag-tomato-paste.f47c362fb0f0eb582f3bc68cf3855fb43a805106395358d41896a269c210b7b4.hk.png differ diff --git a/translated_images/optical-tomato-sorting.61aa134bdda4e5b1bfb16a212c1e35a6ef0c426cbb8b1c975f79d7bfbf48d068.es.png b/translated_images/optical-tomato-sorting.61aa134bdda4e5b1bfb16a212c1e35a6ef0c426cbb8b1c975f79d7bfbf48d068.es.png new file mode 100644 index 00000000..1e7934c3 Binary files /dev/null and b/translated_images/optical-tomato-sorting.61aa134bdda4e5b1bfb16a212c1e35a6ef0c426cbb8b1c975f79d7bfbf48d068.es.png differ diff --git a/translated_images/optical-tomato-sorting.61aa134bdda4e5b1bfb16a212c1e35a6ef0c426cbb8b1c975f79d7bfbf48d068.hk.png b/translated_images/optical-tomato-sorting.61aa134bdda4e5b1bfb16a212c1e35a6ef0c426cbb8b1c975f79d7bfbf48d068.hk.png new file mode 100644 index 00000000..1e7934c3 Binary files /dev/null and b/translated_images/optical-tomato-sorting.61aa134bdda4e5b1bfb16a212c1e35a6ef0c426cbb8b1c975f79d7bfbf48d068.hk.png differ diff --git a/translated_images/overlap-object-detection.d431e03cae75072a2760430eca7f2c5fdd43045bfd72dadcbf12711f7cd6c2ae.es.png b/translated_images/overlap-object-detection.d431e03cae75072a2760430eca7f2c5fdd43045bfd72dadcbf12711f7cd6c2ae.es.png new file mode 100644 index 00000000..5bb319ec Binary files /dev/null and b/translated_images/overlap-object-detection.d431e03cae75072a2760430eca7f2c5fdd43045bfd72dadcbf12711f7cd6c2ae.es.png differ diff --git a/translated_images/overlap-object-detection.d431e03cae75072a2760430eca7f2c5fdd43045bfd72dadcbf12711f7cd6c2ae.hk.png b/translated_images/overlap-object-detection.d431e03cae75072a2760430eca7f2c5fdd43045bfd72dadcbf12711f7cd6c2ae.hk.png new file mode 100644 index 00000000..5bb319ec Binary files /dev/null and b/translated_images/overlap-object-detection.d431e03cae75072a2760430eca7f2c5fdd43045bfd72dadcbf12711f7cd6c2ae.hk.png differ diff --git a/translated_images/pi-button.c7a1a4f55943341ce1baf1057658e9a205804d4131d258e820c93f951df0abf3.es.png b/translated_images/pi-button.c7a1a4f55943341ce1baf1057658e9a205804d4131d258e820c93f951df0abf3.es.png new file mode 100644 index 00000000..d66e224f Binary files /dev/null and b/translated_images/pi-button.c7a1a4f55943341ce1baf1057658e9a205804d4131d258e820c93f951df0abf3.es.png differ diff --git a/translated_images/pi-button.c7a1a4f55943341ce1baf1057658e9a205804d4131d258e820c93f951df0abf3.hk.png b/translated_images/pi-button.c7a1a4f55943341ce1baf1057658e9a205804d4131d258e820c93f951df0abf3.hk.png new file mode 100644 index 00000000..d66e224f Binary files /dev/null and b/translated_images/pi-button.c7a1a4f55943341ce1baf1057658e9a205804d4131d258e820c93f951df0abf3.hk.png differ diff --git a/translated_images/pi-camera-module.4278753c31bd6e757aa2b858be97d72049f71616278cefe4fb5abb485b40a078.es.png b/translated_images/pi-camera-module.4278753c31bd6e757aa2b858be97d72049f71616278cefe4fb5abb485b40a078.es.png new file mode 100644 index 00000000..ed18e7b0 Binary files /dev/null and b/translated_images/pi-camera-module.4278753c31bd6e757aa2b858be97d72049f71616278cefe4fb5abb485b40a078.es.png differ diff --git a/translated_images/pi-camera-module.4278753c31bd6e757aa2b858be97d72049f71616278cefe4fb5abb485b40a078.hk.png b/translated_images/pi-camera-module.4278753c31bd6e757aa2b858be97d72049f71616278cefe4fb5abb485b40a078.hk.png new file mode 100644 index 00000000..ed18e7b0 Binary files /dev/null and b/translated_images/pi-camera-module.4278753c31bd6e757aa2b858be97d72049f71616278cefe4fb5abb485b40a078.hk.png differ diff --git a/translated_images/pi-camera-ribbon-cable.0bf82acd251611c21ac616f082849413e2b322a261d0e4f8fec344248083b07e.es.png b/translated_images/pi-camera-ribbon-cable.0bf82acd251611c21ac616f082849413e2b322a261d0e4f8fec344248083b07e.es.png new file mode 100644 index 00000000..9acb21a7 Binary files /dev/null and b/translated_images/pi-camera-ribbon-cable.0bf82acd251611c21ac616f082849413e2b322a261d0e4f8fec344248083b07e.es.png differ diff --git a/translated_images/pi-camera-ribbon-cable.0bf82acd251611c21ac616f082849413e2b322a261d0e4f8fec344248083b07e.hk.png b/translated_images/pi-camera-ribbon-cable.0bf82acd251611c21ac616f082849413e2b322a261d0e4f8fec344248083b07e.hk.png new file mode 100644 index 00000000..9acb21a7 Binary files /dev/null and b/translated_images/pi-camera-ribbon-cable.0bf82acd251611c21ac616f082849413e2b322a261d0e4f8fec344248083b07e.hk.png differ diff --git a/translated_images/pi-camera-socket-ribbon-cable.a18309920b11800911082ed7aa6fb28e6d9be3a022e4079ff990016cae3fca10.es.png b/translated_images/pi-camera-socket-ribbon-cable.a18309920b11800911082ed7aa6fb28e6d9be3a022e4079ff990016cae3fca10.es.png new file mode 100644 index 00000000..1ced5fc1 Binary files /dev/null and b/translated_images/pi-camera-socket-ribbon-cable.a18309920b11800911082ed7aa6fb28e6d9be3a022e4079ff990016cae3fca10.es.png differ diff --git a/translated_images/pi-camera-socket-ribbon-cable.a18309920b11800911082ed7aa6fb28e6d9be3a022e4079ff990016cae3fca10.hk.png b/translated_images/pi-camera-socket-ribbon-cable.a18309920b11800911082ed7aa6fb28e6d9be3a022e4079ff990016cae3fca10.hk.png new file mode 100644 index 00000000..1ced5fc1 Binary files /dev/null and b/translated_images/pi-camera-socket-ribbon-cable.a18309920b11800911082ed7aa6fb28e6d9be3a022e4079ff990016cae3fca10.hk.png differ diff --git a/translated_images/pi-camera-upside-down.5376961ba31459883362124152ad6b823d5ac5fc14e85f317e22903bd681c2b6.es.png b/translated_images/pi-camera-upside-down.5376961ba31459883362124152ad6b823d5ac5fc14e85f317e22903bd681c2b6.es.png new file mode 100644 index 00000000..7293ced1 Binary files /dev/null and b/translated_images/pi-camera-upside-down.5376961ba31459883362124152ad6b823d5ac5fc14e85f317e22903bd681c2b6.es.png differ diff --git a/translated_images/pi-camera-upside-down.5376961ba31459883362124152ad6b823d5ac5fc14e85f317e22903bd681c2b6.hk.png b/translated_images/pi-camera-upside-down.5376961ba31459883362124152ad6b823d5ac5fc14e85f317e22903bd681c2b6.hk.png new file mode 100644 index 00000000..7293ced1 Binary files /dev/null and b/translated_images/pi-camera-upside-down.5376961ba31459883362124152ad6b823d5ac5fc14e85f317e22903bd681c2b6.hk.png differ diff --git a/translated_images/pi-gps-sensor.1f99ee2b2f6528915047ec78967bd362e0e4ee0ed594368a3837b9cf9cdaca64.es.png b/translated_images/pi-gps-sensor.1f99ee2b2f6528915047ec78967bd362e0e4ee0ed594368a3837b9cf9cdaca64.es.png new file mode 100644 index 00000000..be837c63 Binary files /dev/null and b/translated_images/pi-gps-sensor.1f99ee2b2f6528915047ec78967bd362e0e4ee0ed594368a3837b9cf9cdaca64.es.png differ diff --git a/translated_images/pi-gps-sensor.1f99ee2b2f6528915047ec78967bd362e0e4ee0ed594368a3837b9cf9cdaca64.hk.png b/translated_images/pi-gps-sensor.1f99ee2b2f6528915047ec78967bd362e0e4ee0ed594368a3837b9cf9cdaca64.hk.png new file mode 100644 index 00000000..be837c63 Binary files /dev/null and b/translated_images/pi-gps-sensor.1f99ee2b2f6528915047ec78967bd362e0e4ee0ed594368a3837b9cf9cdaca64.hk.png differ diff --git a/translated_images/pi-hardware-kit.26dbadaedb7dd44c73b0131d5d68ea29472ed0a9744f90d5866c6d82f2d16380.es.png b/translated_images/pi-hardware-kit.26dbadaedb7dd44c73b0131d5d68ea29472ed0a9744f90d5866c6d82f2d16380.es.png new file mode 100644 index 00000000..73861107 Binary files /dev/null and b/translated_images/pi-hardware-kit.26dbadaedb7dd44c73b0131d5d68ea29472ed0a9744f90d5866c6d82f2d16380.es.png differ diff --git a/translated_images/pi-hardware-kit.26dbadaedb7dd44c73b0131d5d68ea29472ed0a9744f90d5866c6d82f2d16380.hk.png b/translated_images/pi-hardware-kit.26dbadaedb7dd44c73b0131d5d68ea29472ed0a9744f90d5866c6d82f2d16380.hk.png new file mode 100644 index 00000000..73861107 Binary files /dev/null and b/translated_images/pi-hardware-kit.26dbadaedb7dd44c73b0131d5d68ea29472ed0a9744f90d5866c6d82f2d16380.hk.png differ diff --git a/translated_images/pi-led.97f1d474981dc35d1c7996c7b17de355d3d0a6bc9606d79fa5f89df933415122.es.png b/translated_images/pi-led.97f1d474981dc35d1c7996c7b17de355d3d0a6bc9606d79fa5f89df933415122.es.png new file mode 100644 index 00000000..1b26d7ff Binary files /dev/null and b/translated_images/pi-led.97f1d474981dc35d1c7996c7b17de355d3d0a6bc9606d79fa5f89df933415122.es.png differ diff --git a/translated_images/pi-led.97f1d474981dc35d1c7996c7b17de355d3d0a6bc9606d79fa5f89df933415122.hk.png b/translated_images/pi-led.97f1d474981dc35d1c7996c7b17de355d3d0a6bc9606d79fa5f89df933415122.hk.png new file mode 100644 index 00000000..1b26d7ff Binary files /dev/null and b/translated_images/pi-led.97f1d474981dc35d1c7996c7b17de355d3d0a6bc9606d79fa5f89df933415122.hk.png differ diff --git a/translated_images/pi-light-sensor.66cc1e31fa48cd7d5f23400d4b2119aa41508275cb7c778053a7923b4e972d7e.es.png b/translated_images/pi-light-sensor.66cc1e31fa48cd7d5f23400d4b2119aa41508275cb7c778053a7923b4e972d7e.es.png new file mode 100644 index 00000000..f1905ecc Binary files /dev/null and b/translated_images/pi-light-sensor.66cc1e31fa48cd7d5f23400d4b2119aa41508275cb7c778053a7923b4e972d7e.es.png differ diff --git a/translated_images/pi-light-sensor.66cc1e31fa48cd7d5f23400d4b2119aa41508275cb7c778053a7923b4e972d7e.hk.png b/translated_images/pi-light-sensor.66cc1e31fa48cd7d5f23400d4b2119aa41508275cb7c778053a7923b4e972d7e.hk.png new file mode 100644 index 00000000..f1905ecc Binary files /dev/null and b/translated_images/pi-light-sensor.66cc1e31fa48cd7d5f23400d4b2119aa41508275cb7c778053a7923b4e972d7e.hk.png differ diff --git a/translated_images/pi-relay-and-soil-moisture-sensor.02f3198975b8c53e69ec716cd2719ce117700bd1fc933eaf93476c103c57939b.es.png b/translated_images/pi-relay-and-soil-moisture-sensor.02f3198975b8c53e69ec716cd2719ce117700bd1fc933eaf93476c103c57939b.es.png new file mode 100644 index 00000000..edc44fa9 Binary files /dev/null and b/translated_images/pi-relay-and-soil-moisture-sensor.02f3198975b8c53e69ec716cd2719ce117700bd1fc933eaf93476c103c57939b.es.png differ diff --git a/translated_images/pi-relay-and-soil-moisture-sensor.02f3198975b8c53e69ec716cd2719ce117700bd1fc933eaf93476c103c57939b.hk.png b/translated_images/pi-relay-and-soil-moisture-sensor.02f3198975b8c53e69ec716cd2719ce117700bd1fc933eaf93476c103c57939b.hk.png new file mode 100644 index 00000000..edc44fa9 Binary files /dev/null and b/translated_images/pi-relay-and-soil-moisture-sensor.02f3198975b8c53e69ec716cd2719ce117700bd1fc933eaf93476c103c57939b.hk.png differ diff --git a/translated_images/pi-respeaker-hat.f00fabe7dd039a93e2e0aa0fc946c9af0c6a9eb17c32fa1ca097fb4e384f69f0.es.png b/translated_images/pi-respeaker-hat.f00fabe7dd039a93e2e0aa0fc946c9af0c6a9eb17c32fa1ca097fb4e384f69f0.es.png new file mode 100644 index 00000000..87854d3a Binary files /dev/null and b/translated_images/pi-respeaker-hat.f00fabe7dd039a93e2e0aa0fc946c9af0c6a9eb17c32fa1ca097fb4e384f69f0.es.png differ diff --git a/translated_images/pi-respeaker-hat.f00fabe7dd039a93e2e0aa0fc946c9af0c6a9eb17c32fa1ca097fb4e384f69f0.hk.png b/translated_images/pi-respeaker-hat.f00fabe7dd039a93e2e0aa0fc946c9af0c6a9eb17c32fa1ca097fb4e384f69f0.hk.png new file mode 100644 index 00000000..87854d3a Binary files /dev/null and b/translated_images/pi-respeaker-hat.f00fabe7dd039a93e2e0aa0fc946c9af0c6a9eb17c32fa1ca097fb4e384f69f0.hk.png differ diff --git a/translated_images/pi-soil-moisture-sensor.fdd7eb2393792cf6739cacf1985d9f55beda16d372f30d0b5a51d586f978a870.es.png b/translated_images/pi-soil-moisture-sensor.fdd7eb2393792cf6739cacf1985d9f55beda16d372f30d0b5a51d586f978a870.es.png new file mode 100644 index 00000000..d1158e0d Binary files /dev/null and b/translated_images/pi-soil-moisture-sensor.fdd7eb2393792cf6739cacf1985d9f55beda16d372f30d0b5a51d586f978a870.es.png differ diff --git a/translated_images/pi-soil-moisture-sensor.fdd7eb2393792cf6739cacf1985d9f55beda16d372f30d0b5a51d586f978a870.hk.png b/translated_images/pi-soil-moisture-sensor.fdd7eb2393792cf6739cacf1985d9f55beda16d372f30d0b5a51d586f978a870.hk.png new file mode 100644 index 00000000..d1158e0d Binary files /dev/null and b/translated_images/pi-soil-moisture-sensor.fdd7eb2393792cf6739cacf1985d9f55beda16d372f30d0b5a51d586f978a870.hk.png differ diff --git a/translated_images/pi-temperature-sensor.3ff82fff672c8e565ef25a39d26d111de006b825a7e0867227ef4e7fbff8553c.es.png b/translated_images/pi-temperature-sensor.3ff82fff672c8e565ef25a39d26d111de006b825a7e0867227ef4e7fbff8553c.es.png new file mode 100644 index 00000000..122abea4 Binary files /dev/null and b/translated_images/pi-temperature-sensor.3ff82fff672c8e565ef25a39d26d111de006b825a7e0867227ef4e7fbff8553c.es.png differ diff --git a/translated_images/pi-temperature-sensor.3ff82fff672c8e565ef25a39d26d111de006b825a7e0867227ef4e7fbff8553c.hk.png b/translated_images/pi-temperature-sensor.3ff82fff672c8e565ef25a39d26d111de006b825a7e0867227ef4e7fbff8553c.hk.png new file mode 100644 index 00000000..122abea4 Binary files /dev/null and b/translated_images/pi-temperature-sensor.3ff82fff672c8e565ef25a39d26d111de006b825a7e0867227ef4e7fbff8553c.hk.png differ diff --git a/translated_images/pi-time-of-flight-sensor.58c8dc04eb3bfb57a7c3019f031433ef4d798d4d7603d565afbf6f3802840dba.es.png b/translated_images/pi-time-of-flight-sensor.58c8dc04eb3bfb57a7c3019f031433ef4d798d4d7603d565afbf6f3802840dba.es.png new file mode 100644 index 00000000..dc009aa5 Binary files /dev/null and b/translated_images/pi-time-of-flight-sensor.58c8dc04eb3bfb57a7c3019f031433ef4d798d4d7603d565afbf6f3802840dba.es.png differ diff --git a/translated_images/pi-time-of-flight-sensor.58c8dc04eb3bfb57a7c3019f031433ef4d798d4d7603d565afbf6f3802840dba.hk.png b/translated_images/pi-time-of-flight-sensor.58c8dc04eb3bfb57a7c3019f031433ef4d798d4d7603d565afbf6f3802840dba.hk.png new file mode 100644 index 00000000..dc009aa5 Binary files /dev/null and b/translated_images/pi-time-of-flight-sensor.58c8dc04eb3bfb57a7c3019f031433ef4d798d4d7603d565afbf6f3802840dba.hk.png differ diff --git a/translated_images/plant-growth-temp-graph copy.65baa28afd9b7f5fbc04bf7c9684b086c466a467631568c23549d54949fc71d2.es.png b/translated_images/plant-growth-temp-graph copy.65baa28afd9b7f5fbc04bf7c9684b086c466a467631568c23549d54949fc71d2.es.png new file mode 100644 index 00000000..ccb0d4e1 Binary files /dev/null and b/translated_images/plant-growth-temp-graph copy.65baa28afd9b7f5fbc04bf7c9684b086c466a467631568c23549d54949fc71d2.es.png differ diff --git a/translated_images/plant-growth-temp-graph copy.65baa28afd9b7f5fbc04bf7c9684b086c466a467631568c23549d54949fc71d2.hk.png b/translated_images/plant-growth-temp-graph copy.65baa28afd9b7f5fbc04bf7c9684b086c466a467631568c23549d54949fc71d2.hk.png new file mode 100644 index 00000000..ccb0d4e1 Binary files /dev/null and b/translated_images/plant-growth-temp-graph copy.65baa28afd9b7f5fbc04bf7c9684b086c466a467631568c23549d54949fc71d2.hk.png differ diff --git a/translated_images/plant-growth-temp-graph.c6d69c9478e6ca832baa8dcb8d4adcbb67304074ce50e94ac8faae95975177f9.es.png b/translated_images/plant-growth-temp-graph.c6d69c9478e6ca832baa8dcb8d4adcbb67304074ce50e94ac8faae95975177f9.es.png new file mode 100644 index 00000000..ccb0d4e1 Binary files /dev/null and b/translated_images/plant-growth-temp-graph.c6d69c9478e6ca832baa8dcb8d4adcbb67304074ce50e94ac8faae95975177f9.es.png differ diff --git a/translated_images/plant-growth-temp-graph.c6d69c9478e6ca832baa8dcb8d4adcbb67304074ce50e94ac8faae95975177f9.hk.png b/translated_images/plant-growth-temp-graph.c6d69c9478e6ca832baa8dcb8d4adcbb67304074ce50e94ac8faae95975177f9.hk.png new file mode 100644 index 00000000..ccb0d4e1 Binary files /dev/null and b/translated_images/plant-growth-temp-graph.c6d69c9478e6ca832baa8dcb8d4adcbb67304074ce50e94ac8faae95975177f9.hk.png differ diff --git a/translated_images/polygon-points.302193da381cb415f46c2c7a98496ee4be05d6c73d21238a89721ad93e121233.es.png b/translated_images/polygon-points.302193da381cb415f46c2c7a98496ee4be05d6c73d21238a89721ad93e121233.es.png new file mode 100644 index 00000000..12274b8b Binary files /dev/null and b/translated_images/polygon-points.302193da381cb415f46c2c7a98496ee4be05d6c73d21238a89721ad93e121233.es.png differ diff --git a/translated_images/polygon-points.302193da381cb415f46c2c7a98496ee4be05d6c73d21238a89721ad93e121233.hk.png b/translated_images/polygon-points.302193da381cb415f46c2c7a98496ee4be05d6c73d21238a89721ad93e121233.hk.png new file mode 100644 index 00000000..12274b8b Binary files /dev/null and b/translated_images/polygon-points.302193da381cb415f46c2c7a98496ee4be05d6c73d21238a89721ad93e121233.hk.png differ diff --git a/translated_images/potentiometer.35a348b9ce22f6ec1199ad37d68692d04185456ccbc2541a454bb6698be9f19c.es.png b/translated_images/potentiometer.35a348b9ce22f6ec1199ad37d68692d04185456ccbc2541a454bb6698be9f19c.es.png new file mode 100644 index 00000000..da226797 Binary files /dev/null and b/translated_images/potentiometer.35a348b9ce22f6ec1199ad37d68692d04185456ccbc2541a454bb6698be9f19c.es.png differ diff --git a/translated_images/potentiometer.35a348b9ce22f6ec1199ad37d68692d04185456ccbc2541a454bb6698be9f19c.hk.png b/translated_images/potentiometer.35a348b9ce22f6ec1199ad37d68692d04185456ccbc2541a454bb6698be9f19c.hk.png new file mode 100644 index 00000000..da226797 Binary files /dev/null and b/translated_images/potentiometer.35a348b9ce22f6ec1199ad37d68692d04185456ccbc2541a454bb6698be9f19c.hk.png differ diff --git a/translated_images/proximity-sensor.f5cd752c77fb62fea000156233b32fd24fad3707ec69b8bdd8d312b7af85156d.es.png b/translated_images/proximity-sensor.f5cd752c77fb62fea000156233b32fd24fad3707ec69b8bdd8d312b7af85156d.es.png new file mode 100644 index 00000000..67bd8a82 Binary files /dev/null and b/translated_images/proximity-sensor.f5cd752c77fb62fea000156233b32fd24fad3707ec69b8bdd8d312b7af85156d.es.png differ diff --git a/translated_images/proximity-sensor.f5cd752c77fb62fea000156233b32fd24fad3707ec69b8bdd8d312b7af85156d.hk.png b/translated_images/proximity-sensor.f5cd752c77fb62fea000156233b32fd24fad3707ec69b8bdd8d312b7af85156d.hk.png new file mode 100644 index 00000000..67bd8a82 Binary files /dev/null and b/translated_images/proximity-sensor.f5cd752c77fb62fea000156233b32fd24fad3707ec69b8bdd8d312b7af85156d.hk.png differ diff --git a/translated_images/pub-sub.7c7ed43fe9fd15d4e1f81a3fd95440413c457acd9bcbe9a43341e30e88db5264.es.png b/translated_images/pub-sub.7c7ed43fe9fd15d4e1f81a3fd95440413c457acd9bcbe9a43341e30e88db5264.es.png new file mode 100644 index 00000000..18938f59 Binary files /dev/null and b/translated_images/pub-sub.7c7ed43fe9fd15d4e1f81a3fd95440413c457acd9bcbe9a43341e30e88db5264.es.png differ diff --git a/translated_images/pub-sub.7c7ed43fe9fd15d4e1f81a3fd95440413c457acd9bcbe9a43341e30e88db5264.hk.png b/translated_images/pub-sub.7c7ed43fe9fd15d4e1f81a3fd95440413c457acd9bcbe9a43341e30e88db5264.hk.png new file mode 100644 index 00000000..18938f59 Binary files /dev/null and b/translated_images/pub-sub.7c7ed43fe9fd15d4e1f81a3fd95440413c457acd9bcbe9a43341e30e88db5264.hk.png differ diff --git a/translated_images/pump-wired-to-relay.66c5cfc0d89189900cd601777f5caeb39ee35c6250f6c86bf38feaceedb21fe9.es.png b/translated_images/pump-wired-to-relay.66c5cfc0d89189900cd601777f5caeb39ee35c6250f6c86bf38feaceedb21fe9.es.png new file mode 100644 index 00000000..db480604 Binary files /dev/null and b/translated_images/pump-wired-to-relay.66c5cfc0d89189900cd601777f5caeb39ee35c6250f6c86bf38feaceedb21fe9.es.png differ diff --git a/translated_images/pump-wired-to-relay.66c5cfc0d89189900cd601777f5caeb39ee35c6250f6c86bf38feaceedb21fe9.hk.png b/translated_images/pump-wired-to-relay.66c5cfc0d89189900cd601777f5caeb39ee35c6250f6c86bf38feaceedb21fe9.hk.png new file mode 100644 index 00000000..db480604 Binary files /dev/null and b/translated_images/pump-wired-to-relay.66c5cfc0d89189900cd601777f5caeb39ee35c6250f6c86bf38feaceedb21fe9.hk.png differ diff --git a/translated_images/pwm-motor-150rpm.83347ac04ca38482bd120939b133803963c9c15ca9d8d484712a4bd92820f6a4.es.png b/translated_images/pwm-motor-150rpm.83347ac04ca38482bd120939b133803963c9c15ca9d8d484712a4bd92820f6a4.es.png new file mode 100644 index 00000000..535e5798 Binary files /dev/null and b/translated_images/pwm-motor-150rpm.83347ac04ca38482bd120939b133803963c9c15ca9d8d484712a4bd92820f6a4.es.png differ diff --git a/translated_images/pwm-motor-150rpm.83347ac04ca38482bd120939b133803963c9c15ca9d8d484712a4bd92820f6a4.hk.png b/translated_images/pwm-motor-150rpm.83347ac04ca38482bd120939b133803963c9c15ca9d8d484712a4bd92820f6a4.hk.png new file mode 100644 index 00000000..535e5798 Binary files /dev/null and b/translated_images/pwm-motor-150rpm.83347ac04ca38482bd120939b133803963c9c15ca9d8d484712a4bd92820f6a4.hk.png differ diff --git a/translated_images/pwm-motor-75rpm.a5e4c939934b6e14fd9e98e4f2c9539d723da2b18f490eae0948dd044d18ff7e.es.png b/translated_images/pwm-motor-75rpm.a5e4c939934b6e14fd9e98e4f2c9539d723da2b18f490eae0948dd044d18ff7e.es.png new file mode 100644 index 00000000..b3d83ab7 Binary files /dev/null and b/translated_images/pwm-motor-75rpm.a5e4c939934b6e14fd9e98e4f2c9539d723da2b18f490eae0948dd044d18ff7e.es.png differ diff --git a/translated_images/pwm-motor-75rpm.a5e4c939934b6e14fd9e98e4f2c9539d723da2b18f490eae0948dd044d18ff7e.hk.png b/translated_images/pwm-motor-75rpm.a5e4c939934b6e14fd9e98e4f2c9539d723da2b18f490eae0948dd044d18ff7e.hk.png new file mode 100644 index 00000000..b3d83ab7 Binary files /dev/null and b/translated_images/pwm-motor-75rpm.a5e4c939934b6e14fd9e98e4f2c9539d723da2b18f490eae0948dd044d18ff7e.hk.png differ diff --git a/translated_images/ram-comparison.6beb73541b42ac6ffde64cdf79fc925a84b932ce7ebd4d41d5fd7afc1257a696.es.png b/translated_images/ram-comparison.6beb73541b42ac6ffde64cdf79fc925a84b932ce7ebd4d41d5fd7afc1257a696.es.png new file mode 100644 index 00000000..4bb97d60 Binary files /dev/null and b/translated_images/ram-comparison.6beb73541b42ac6ffde64cdf79fc925a84b932ce7ebd4d41d5fd7afc1257a696.es.png differ diff --git a/translated_images/ram-comparison.6beb73541b42ac6ffde64cdf79fc925a84b932ce7ebd4d41d5fd7afc1257a696.hk.png b/translated_images/ram-comparison.6beb73541b42ac6ffde64cdf79fc925a84b932ce7ebd4d41d5fd7afc1257a696.hk.png new file mode 100644 index 00000000..4bb97d60 Binary files /dev/null and b/translated_images/ram-comparison.6beb73541b42ac6ffde64cdf79fc925a84b932ce7ebd4d41d5fd7afc1257a696.hk.png differ diff --git a/translated_images/raspberry-pi-4.fd4590d308c3d456db1327e86b395ddcd735513267aafd4879ea2785f7792eac.es.jpg b/translated_images/raspberry-pi-4.fd4590d308c3d456db1327e86b395ddcd735513267aafd4879ea2785f7792eac.es.jpg new file mode 100644 index 00000000..4cf0d73d Binary files /dev/null and b/translated_images/raspberry-pi-4.fd4590d308c3d456db1327e86b395ddcd735513267aafd4879ea2785f7792eac.es.jpg differ diff --git a/translated_images/raspberry-pi-4.fd4590d308c3d456db1327e86b395ddcd735513267aafd4879ea2785f7792eac.hk.jpg b/translated_images/raspberry-pi-4.fd4590d308c3d456db1327e86b395ddcd735513267aafd4879ea2785f7792eac.hk.jpg new file mode 100644 index 00000000..4cf0d73d Binary files /dev/null and b/translated_images/raspberry-pi-4.fd4590d308c3d456db1327e86b395ddcd735513267aafd4879ea2785f7792eac.hk.jpg differ diff --git a/translated_images/raspberry-pi-imager.24aedeab9e233d841a1504ed7cfeb871b1f8e1134cfcd8370e7f60a092056be2.es.png b/translated_images/raspberry-pi-imager.24aedeab9e233d841a1504ed7cfeb871b1f8e1134cfcd8370e7f60a092056be2.es.png new file mode 100644 index 00000000..0aace880 Binary files /dev/null and b/translated_images/raspberry-pi-imager.24aedeab9e233d841a1504ed7cfeb871b1f8e1134cfcd8370e7f60a092056be2.es.png differ diff --git a/translated_images/raspberry-pi-imager.24aedeab9e233d841a1504ed7cfeb871b1f8e1134cfcd8370e7f60a092056be2.hk.png b/translated_images/raspberry-pi-imager.24aedeab9e233d841a1504ed7cfeb871b1f8e1134cfcd8370e7f60a092056be2.hk.png new file mode 100644 index 00000000..0aace880 Binary files /dev/null and b/translated_images/raspberry-pi-imager.24aedeab9e233d841a1504ed7cfeb871b1f8e1134cfcd8370e7f60a092056be2.hk.png differ diff --git a/translated_images/raspberry-pi-logo.4efaa16605cee05489d8fa53941e991b3757aa24c20a95abdcf8cfd761953596.es.png b/translated_images/raspberry-pi-logo.4efaa16605cee05489d8fa53941e991b3757aa24c20a95abdcf8cfd761953596.es.png new file mode 100644 index 00000000..b19b1f6b Binary files /dev/null and b/translated_images/raspberry-pi-logo.4efaa16605cee05489d8fa53941e991b3757aa24c20a95abdcf8cfd761953596.es.png differ diff --git a/translated_images/raspberry-pi-logo.4efaa16605cee05489d8fa53941e991b3757aa24c20a95abdcf8cfd761953596.hk.png b/translated_images/raspberry-pi-logo.4efaa16605cee05489d8fa53941e991b3757aa24c20a95abdcf8cfd761953596.hk.png new file mode 100644 index 00000000..b19b1f6b Binary files /dev/null and b/translated_images/raspberry-pi-logo.4efaa16605cee05489d8fa53941e991b3757aa24c20a95abdcf8cfd761953596.hk.png differ diff --git a/translated_images/raspberry-pi-zero.f7a4133e1e7d54bb3dbb32319b217a53c5b94871995a54647f2894b54206b8d8.es.jpg b/translated_images/raspberry-pi-zero.f7a4133e1e7d54bb3dbb32319b217a53c5b94871995a54647f2894b54206b8d8.es.jpg new file mode 100644 index 00000000..827670ed Binary files /dev/null and b/translated_images/raspberry-pi-zero.f7a4133e1e7d54bb3dbb32319b217a53c5b94871995a54647f2894b54206b8d8.es.jpg differ diff --git a/translated_images/raspberry-pi-zero.f7a4133e1e7d54bb3dbb32319b217a53c5b94871995a54647f2894b54206b8d8.hk.jpg b/translated_images/raspberry-pi-zero.f7a4133e1e7d54bb3dbb32319b217a53c5b94871995a54647f2894b54206b8d8.hk.jpg new file mode 100644 index 00000000..827670ed Binary files /dev/null and b/translated_images/raspberry-pi-zero.f7a4133e1e7d54bb3dbb32319b217a53c5b94871995a54647f2894b54206b8d8.hk.jpg differ diff --git a/translated_images/relay-off.c34a178a2960fecdc3c6400d43e633ed11c6746cd653cfb4a768fa097c40394c.es.png b/translated_images/relay-off.c34a178a2960fecdc3c6400d43e633ed11c6746cd653cfb4a768fa097c40394c.es.png new file mode 100644 index 00000000..435f901a Binary files /dev/null and b/translated_images/relay-off.c34a178a2960fecdc3c6400d43e633ed11c6746cd653cfb4a768fa097c40394c.es.png differ diff --git a/translated_images/relay-off.c34a178a2960fecdc3c6400d43e633ed11c6746cd653cfb4a768fa097c40394c.hk.png b/translated_images/relay-off.c34a178a2960fecdc3c6400d43e633ed11c6746cd653cfb4a768fa097c40394c.hk.png new file mode 100644 index 00000000..435f901a Binary files /dev/null and b/translated_images/relay-off.c34a178a2960fecdc3c6400d43e633ed11c6746cd653cfb4a768fa097c40394c.hk.png differ diff --git a/translated_images/relay-on.4db16a0fd6b669262fd6699aff3fbcd31b6057c06d90411b6bddc06326d1cf75.es.png b/translated_images/relay-on.4db16a0fd6b669262fd6699aff3fbcd31b6057c06d90411b6bddc06326d1cf75.es.png new file mode 100644 index 00000000..7308a1d1 Binary files /dev/null and b/translated_images/relay-on.4db16a0fd6b669262fd6699aff3fbcd31b6057c06d90411b6bddc06326d1cf75.es.png differ diff --git a/translated_images/relay-on.4db16a0fd6b669262fd6699aff3fbcd31b6057c06d90411b6bddc06326d1cf75.hk.png b/translated_images/relay-on.4db16a0fd6b669262fd6699aff3fbcd31b6057c06d90411b6bddc06326d1cf75.hk.png new file mode 100644 index 00000000..7308a1d1 Binary files /dev/null and b/translated_images/relay-on.4db16a0fd6b669262fd6699aff3fbcd31b6057c06d90411b6bddc06326d1cf75.hk.png differ diff --git a/translated_images/resistive-soil-moisture-sensor.728a138a3d109e0653d8e4f6744140836c67461bbd0f4d887f47ed8228dc80b5.es.png b/translated_images/resistive-soil-moisture-sensor.728a138a3d109e0653d8e4f6744140836c67461bbd0f4d887f47ed8228dc80b5.es.png new file mode 100644 index 00000000..8454c4d2 Binary files /dev/null and b/translated_images/resistive-soil-moisture-sensor.728a138a3d109e0653d8e4f6744140836c67461bbd0f4d887f47ed8228dc80b5.es.png differ diff --git a/translated_images/resistive-soil-moisture-sensor.728a138a3d109e0653d8e4f6744140836c67461bbd0f4d887f47ed8228dc80b5.hk.png b/translated_images/resistive-soil-moisture-sensor.728a138a3d109e0653d8e4f6744140836c67461bbd0f4d887f47ed8228dc80b5.hk.png new file mode 100644 index 00000000..8454c4d2 Binary files /dev/null and b/translated_images/resistive-soil-moisture-sensor.728a138a3d109e0653d8e4f6744140836c67461bbd0f4d887f47ed8228dc80b5.hk.png differ diff --git a/translated_images/respeaker-35mm-speaker.ad79ef4f128c7751f0abf854869b6b779c90c12ae3e48909944a7e48aeee3c7e.es.png b/translated_images/respeaker-35mm-speaker.ad79ef4f128c7751f0abf854869b6b779c90c12ae3e48909944a7e48aeee3c7e.es.png new file mode 100644 index 00000000..324b711d Binary files /dev/null and b/translated_images/respeaker-35mm-speaker.ad79ef4f128c7751f0abf854869b6b779c90c12ae3e48909944a7e48aeee3c7e.es.png differ diff --git a/translated_images/respeaker-35mm-speaker.ad79ef4f128c7751f0abf854869b6b779c90c12ae3e48909944a7e48aeee3c7e.hk.png b/translated_images/respeaker-35mm-speaker.ad79ef4f128c7751f0abf854869b6b779c90c12ae3e48909944a7e48aeee3c7e.hk.png new file mode 100644 index 00000000..324b711d Binary files /dev/null and b/translated_images/respeaker-35mm-speaker.ad79ef4f128c7751f0abf854869b6b779c90c12ae3e48909944a7e48aeee3c7e.hk.png differ diff --git a/translated_images/respeaker-jst-speaker.a441d177809df9458041a2012dd336dbb22c00a5c9642647109d2940a50d6fcc.es.png b/translated_images/respeaker-jst-speaker.a441d177809df9458041a2012dd336dbb22c00a5c9642647109d2940a50d6fcc.es.png new file mode 100644 index 00000000..ddfb42aa Binary files /dev/null and b/translated_images/respeaker-jst-speaker.a441d177809df9458041a2012dd336dbb22c00a5c9642647109d2940a50d6fcc.es.png differ diff --git a/translated_images/respeaker-jst-speaker.a441d177809df9458041a2012dd336dbb22c00a5c9642647109d2940a50d6fcc.hk.png b/translated_images/respeaker-jst-speaker.a441d177809df9458041a2012dd336dbb22c00a5c9642647109d2940a50d6fcc.hk.png new file mode 100644 index 00000000..ddfb42aa Binary files /dev/null and b/translated_images/respeaker-jst-speaker.a441d177809df9458041a2012dd336dbb22c00a5c9642647109d2940a50d6fcc.hk.png differ diff --git a/translated_images/respeaker.f5d19d1c6b14ab1676d24ac2764e64fac5339046ae07be8b45ce07633d61b79b.es.png b/translated_images/respeaker.f5d19d1c6b14ab1676d24ac2764e64fac5339046ae07be8b45ce07633d61b79b.es.png new file mode 100644 index 00000000..280f2fe0 Binary files /dev/null and b/translated_images/respeaker.f5d19d1c6b14ab1676d24ac2764e64fac5339046ae07be8b45ce07633d61b79b.es.png differ diff --git a/translated_images/respeaker.f5d19d1c6b14ab1676d24ac2764e64fac5339046ae07be8b45ce07633d61b79b.hk.png b/translated_images/respeaker.f5d19d1c6b14ab1676d24ac2764e64fac5339046ae07be8b45ce07633d61b79b.hk.png new file mode 100644 index 00000000..280f2fe0 Binary files /dev/null and b/translated_images/respeaker.f5d19d1c6b14ab1676d24ac2764e64fac5339046ae07be8b45ce07633d61b79b.hk.png differ diff --git a/translated_images/ribbon-mic.eacc8e092c7441caee6d7a81e2f40e1675bf36269848964c7c09c9a9acb05127.es.jpg b/translated_images/ribbon-mic.eacc8e092c7441caee6d7a81e2f40e1675bf36269848964c7c09c9a9acb05127.es.jpg new file mode 100644 index 00000000..89b581ef Binary files /dev/null and b/translated_images/ribbon-mic.eacc8e092c7441caee6d7a81e2f40e1675bf36269848964c7c09c9a9acb05127.es.jpg differ diff --git a/translated_images/ribbon-mic.eacc8e092c7441caee6d7a81e2f40e1675bf36269848964c7c09c9a9acb05127.hk.jpg b/translated_images/ribbon-mic.eacc8e092c7441caee6d7a81e2f40e1675bf36269848964c7c09c9a9acb05127.hk.jpg new file mode 100644 index 00000000..89b581ef Binary files /dev/null and b/translated_images/ribbon-mic.eacc8e092c7441caee6d7a81e2f40e1675bf36269848964c7c09c9a9acb05127.hk.jpg differ diff --git a/translated_images/rpi-stock-with-bounding-boxes.b5540e2ecb7cd49f1271828d3be412671d950e87625c5597ea97c90f11e01097.es.jpg b/translated_images/rpi-stock-with-bounding-boxes.b5540e2ecb7cd49f1271828d3be412671d950e87625c5597ea97c90f11e01097.es.jpg new file mode 100644 index 00000000..6efd2da1 Binary files /dev/null and b/translated_images/rpi-stock-with-bounding-boxes.b5540e2ecb7cd49f1271828d3be412671d950e87625c5597ea97c90f11e01097.es.jpg differ diff --git a/translated_images/rpi-stock-with-bounding-boxes.b5540e2ecb7cd49f1271828d3be412671d950e87625c5597ea97c90f11e01097.hk.jpg b/translated_images/rpi-stock-with-bounding-boxes.b5540e2ecb7cd49f1271828d3be412671d950e87625c5597ea97c90f11e01097.hk.jpg new file mode 100644 index 00000000..6efd2da1 Binary files /dev/null and b/translated_images/rpi-stock-with-bounding-boxes.b5540e2ecb7cd49f1271828d3be412671d950e87625c5597ea97c90f11e01097.hk.jpg differ diff --git a/translated_images/sampling.6f4fadb3f2d9dfe7618f9edfe75a350e6b3f74293ec84f02ab69c19d2afe3d73.es.png b/translated_images/sampling.6f4fadb3f2d9dfe7618f9edfe75a350e6b3f74293ec84f02ab69c19d2afe3d73.es.png new file mode 100644 index 00000000..348fe7a0 Binary files /dev/null and b/translated_images/sampling.6f4fadb3f2d9dfe7618f9edfe75a350e6b3f74293ec84f02ab69c19d2afe3d73.es.png differ diff --git a/translated_images/sampling.6f4fadb3f2d9dfe7618f9edfe75a350e6b3f74293ec84f02ab69c19d2afe3d73.hk.png b/translated_images/sampling.6f4fadb3f2d9dfe7618f9edfe75a350e6b3f74293ec84f02ab69c19d2afe3d73.hk.png new file mode 100644 index 00000000..348fe7a0 Binary files /dev/null and b/translated_images/sampling.6f4fadb3f2d9dfe7618f9edfe75a350e6b3f74293ec84f02ab69c19d2afe3d73.hk.png differ diff --git a/translated_images/save-telemetry-database.ddc9c6bea0c5ba39449966a463ca6748cd8e2d565dab44ff31c9f1d2f6c21d27.es.png b/translated_images/save-telemetry-database.ddc9c6bea0c5ba39449966a463ca6748cd8e2d565dab44ff31c9f1d2f6c21d27.es.png new file mode 100644 index 00000000..a69e73f4 Binary files /dev/null and b/translated_images/save-telemetry-database.ddc9c6bea0c5ba39449966a463ca6748cd8e2d565dab44ff31c9f1d2f6c21d27.es.png differ diff --git a/translated_images/save-telemetry-database.ddc9c6bea0c5ba39449966a463ca6748cd8e2d565dab44ff31c9f1d2f6c21d27.hk.png b/translated_images/save-telemetry-database.ddc9c6bea0c5ba39449966a463ca6748cd8e2d565dab44ff31c9f1d2f6c21d27.hk.png new file mode 100644 index 00000000..a69e73f4 Binary files /dev/null and b/translated_images/save-telemetry-database.ddc9c6bea0c5ba39449966a463ca6748cd8e2d565dab44ff31c9f1d2f6c21d27.hk.png differ diff --git a/translated_images/save-telemetry-to-storage-from-functions.ed3b1820980097f143d9f0570072da11304c2bc7906359dfa075b4d9b253c20f.es.png b/translated_images/save-telemetry-to-storage-from-functions.ed3b1820980097f143d9f0570072da11304c2bc7906359dfa075b4d9b253c20f.es.png new file mode 100644 index 00000000..49b0ca9b Binary files /dev/null and b/translated_images/save-telemetry-to-storage-from-functions.ed3b1820980097f143d9f0570072da11304c2bc7906359dfa075b4d9b253c20f.es.png differ diff --git a/translated_images/save-telemetry-to-storage-from-functions.ed3b1820980097f143d9f0570072da11304c2bc7906359dfa075b4d9b253c20f.hk.png b/translated_images/save-telemetry-to-storage-from-functions.ed3b1820980097f143d9f0570072da11304c2bc7906359dfa075b4d9b253c20f.hk.png new file mode 100644 index 00000000..49b0ca9b Binary files /dev/null and b/translated_images/save-telemetry-to-storage-from-functions.ed3b1820980097f143d9f0570072da11304c2bc7906359dfa075b4d9b253c20f.hk.png differ diff --git a/translated_images/search-buffer-and-distance.e6a79af3898183c7b2ef6fbf12271b8b34afd23969bb946962b1b18d3d2635e8.es.png b/translated_images/search-buffer-and-distance.e6a79af3898183c7b2ef6fbf12271b8b34afd23969bb946962b1b18d3d2635e8.es.png new file mode 100644 index 00000000..458a3c95 Binary files /dev/null and b/translated_images/search-buffer-and-distance.e6a79af3898183c7b2ef6fbf12271b8b34afd23969bb946962b1b18d3d2635e8.es.png differ diff --git a/translated_images/search-buffer-and-distance.e6a79af3898183c7b2ef6fbf12271b8b34afd23969bb946962b1b18d3d2635e8.hk.png b/translated_images/search-buffer-and-distance.e6a79af3898183c7b2ef6fbf12271b8b34afd23969bb946962b1b18d3d2635e8.hk.png new file mode 100644 index 00000000..458a3c95 Binary files /dev/null and b/translated_images/search-buffer-and-distance.e6a79af3898183c7b2ef6fbf12271b8b34afd23969bb946962b1b18d3d2635e8.hk.png differ diff --git a/translated_images/seeed-logo.74732b6b482b6e8e8bdcc06f0541fc92b1dabf5e3e8f37afb91e04393a8cb977.es.png b/translated_images/seeed-logo.74732b6b482b6e8e8bdcc06f0541fc92b1dabf5e3e8f37afb91e04393a8cb977.es.png new file mode 100644 index 00000000..90b687c2 Binary files /dev/null and b/translated_images/seeed-logo.74732b6b482b6e8e8bdcc06f0541fc92b1dabf5e3e8f37afb91e04393a8cb977.es.png differ diff --git a/translated_images/seeed-logo.74732b6b482b6e8e8bdcc06f0541fc92b1dabf5e3e8f37afb91e04393a8cb977.hk.png b/translated_images/seeed-logo.74732b6b482b6e8e8bdcc06f0541fc92b1dabf5e3e8f37afb91e04393a8cb977.hk.png new file mode 100644 index 00000000..90b687c2 Binary files /dev/null and b/translated_images/seeed-logo.74732b6b482b6e8e8bdcc06f0541fc92b1dabf5e3e8f37afb91e04393a8cb977.hk.png differ diff --git a/translated_images/select-the-random-checkbox-and-set-a-range.32cf4bc7c12e797f8c76616b10c7c23a6592321bb1a6310e0b481e72f97d23b3.es.png b/translated_images/select-the-random-checkbox-and-set-a-range.32cf4bc7c12e797f8c76616b10c7c23a6592321bb1a6310e0b481e72f97d23b3.es.png new file mode 100644 index 00000000..cb4bc445 Binary files /dev/null and b/translated_images/select-the-random-checkbox-and-set-a-range.32cf4bc7c12e797f8c76616b10c7c23a6592321bb1a6310e0b481e72f97d23b3.es.png differ diff --git a/translated_images/select-the-random-checkbox-and-set-a-range.32cf4bc7c12e797f8c76616b10c7c23a6592321bb1a6310e0b481e72f97d23b3.hk.png b/translated_images/select-the-random-checkbox-and-set-a-range.32cf4bc7c12e797f8c76616b10c7c23a6592321bb1a6310e0b481e72f97d23b3.hk.png new file mode 100644 index 00000000..cb4bc445 Binary files /dev/null and b/translated_images/select-the-random-checkbox-and-set-a-range.32cf4bc7c12e797f8c76616b10c7c23a6592321bb1a6310e0b481e72f97d23b3.hk.png differ diff --git a/translated_images/send-message-asymmetric.7abe327c62615b8c19805252af5d4b6c5e7aaeb8fbc455efeff866fe2d300b62.es.png b/translated_images/send-message-asymmetric.7abe327c62615b8c19805252af5d4b6c5e7aaeb8fbc455efeff866fe2d300b62.es.png new file mode 100644 index 00000000..e7ea8ab6 Binary files /dev/null and b/translated_images/send-message-asymmetric.7abe327c62615b8c19805252af5d4b6c5e7aaeb8fbc455efeff866fe2d300b62.es.png differ diff --git a/translated_images/send-message-asymmetric.7abe327c62615b8c19805252af5d4b6c5e7aaeb8fbc455efeff866fe2d300b62.hk.png b/translated_images/send-message-asymmetric.7abe327c62615b8c19805252af5d4b6c5e7aaeb8fbc455efeff866fe2d300b62.hk.png new file mode 100644 index 00000000..e7ea8ab6 Binary files /dev/null and b/translated_images/send-message-asymmetric.7abe327c62615b8c19805252af5d4b6c5e7aaeb8fbc455efeff866fe2d300b62.hk.png differ diff --git a/translated_images/send-message-certificate.9cc576ac1e46b76eb58ebc8eedaa522566fa0700076da46f5180aad78c2435db.es.png b/translated_images/send-message-certificate.9cc576ac1e46b76eb58ebc8eedaa522566fa0700076da46f5180aad78c2435db.es.png new file mode 100644 index 00000000..6f138cf9 Binary files /dev/null and b/translated_images/send-message-certificate.9cc576ac1e46b76eb58ebc8eedaa522566fa0700076da46f5180aad78c2435db.es.png differ diff --git a/translated_images/send-message-certificate.9cc576ac1e46b76eb58ebc8eedaa522566fa0700076da46f5180aad78c2435db.hk.png b/translated_images/send-message-certificate.9cc576ac1e46b76eb58ebc8eedaa522566fa0700076da46f5180aad78c2435db.hk.png new file mode 100644 index 00000000..6f138cf9 Binary files /dev/null and b/translated_images/send-message-certificate.9cc576ac1e46b76eb58ebc8eedaa522566fa0700076da46f5180aad78c2435db.hk.png differ diff --git a/translated_images/send-message-symmetric-key-hacker.e7cb53db1707adfb1486a8144060cb76435fe8dbdede8cecc09e7d15b2d9a251.es.png b/translated_images/send-message-symmetric-key-hacker.e7cb53db1707adfb1486a8144060cb76435fe8dbdede8cecc09e7d15b2d9a251.es.png new file mode 100644 index 00000000..2f5f2861 Binary files /dev/null and b/translated_images/send-message-symmetric-key-hacker.e7cb53db1707adfb1486a8144060cb76435fe8dbdede8cecc09e7d15b2d9a251.es.png differ diff --git a/translated_images/send-message-symmetric-key-hacker.e7cb53db1707adfb1486a8144060cb76435fe8dbdede8cecc09e7d15b2d9a251.hk.png b/translated_images/send-message-symmetric-key-hacker.e7cb53db1707adfb1486a8144060cb76435fe8dbdede8cecc09e7d15b2d9a251.hk.png new file mode 100644 index 00000000..2f5f2861 Binary files /dev/null and b/translated_images/send-message-symmetric-key-hacker.e7cb53db1707adfb1486a8144060cb76435fe8dbdede8cecc09e7d15b2d9a251.hk.png differ diff --git a/translated_images/send-message-symmetric-key.a2e8ad0d495896ffcdf15d25bb4491c695a5cb851457b359fb0f0c89d67707c9.es.png b/translated_images/send-message-symmetric-key.a2e8ad0d495896ffcdf15d25bb4491c695a5cb851457b359fb0f0c89d67707c9.es.png new file mode 100644 index 00000000..f2f1b63e Binary files /dev/null and b/translated_images/send-message-symmetric-key.a2e8ad0d495896ffcdf15d25bb4491c695a5cb851457b359fb0f0c89d67707c9.es.png differ diff --git a/translated_images/send-message-symmetric-key.a2e8ad0d495896ffcdf15d25bb4491c695a5cb851457b359fb0f0c89d67707c9.hk.png b/translated_images/send-message-symmetric-key.a2e8ad0d495896ffcdf15d25bb4491c695a5cb851457b359fb0f0c89d67707c9.hk.png new file mode 100644 index 00000000..f2f1b63e Binary files /dev/null and b/translated_images/send-message-symmetric-key.a2e8ad0d495896ffcdf15d25bb4491c695a5cb851457b359fb0f0c89d67707c9.hk.png differ diff --git a/translated_images/sentence-as-intent-entities.301401696f9922590a99343f5c5d211b710b906f212f0d4d034cee3ffb610272.es.png b/translated_images/sentence-as-intent-entities.301401696f9922590a99343f5c5d211b710b906f212f0d4d034cee3ffb610272.es.png new file mode 100644 index 00000000..5643c164 Binary files /dev/null and b/translated_images/sentence-as-intent-entities.301401696f9922590a99343f5c5d211b710b906f212f0d4d034cee3ffb610272.es.png differ diff --git a/translated_images/sentence-as-intent-entities.301401696f9922590a99343f5c5d211b710b906f212f0d4d034cee3ffb610272.hk.png b/translated_images/sentence-as-intent-entities.301401696f9922590a99343f5c5d211b710b906f212f0d4d034cee3ffb610272.hk.png new file mode 100644 index 00000000..5643c164 Binary files /dev/null and b/translated_images/sentence-as-intent-entities.301401696f9922590a99343f5c5d211b710b906f212f0d4d034cee3ffb610272.hk.png differ diff --git a/translated_images/serverless-scaling.f8c769adf0413fd17be1af4f07ff63016b347e2ff869be6c4abb211f9e93909d.es.png b/translated_images/serverless-scaling.f8c769adf0413fd17be1af4f07ff63016b347e2ff869be6c4abb211f9e93909d.es.png new file mode 100644 index 00000000..73fa30d1 Binary files /dev/null and b/translated_images/serverless-scaling.f8c769adf0413fd17be1af4f07ff63016b347e2ff869be6c4abb211f9e93909d.es.png differ diff --git a/translated_images/serverless-scaling.f8c769adf0413fd17be1af4f07ff63016b347e2ff869be6c4abb211f9e93909d.hk.png b/translated_images/serverless-scaling.f8c769adf0413fd17be1af4f07ff63016b347e2ff869be6c4abb211f9e93909d.hk.png new file mode 100644 index 00000000..73fa30d1 Binary files /dev/null and b/translated_images/serverless-scaling.f8c769adf0413fd17be1af4f07ff63016b347e2ff869be6c4abb211f9e93909d.hk.png differ diff --git a/translated_images/shapes-to-images.1a309f0ea88dd66fafa4da6d38e88806ce174cc6a88081efb32852230ed55de8.es.png b/translated_images/shapes-to-images.1a309f0ea88dd66fafa4da6d38e88806ce174cc6a88081efb32852230ed55de8.es.png new file mode 100644 index 00000000..eee39f7d Binary files /dev/null and b/translated_images/shapes-to-images.1a309f0ea88dd66fafa4da6d38e88806ce174cc6a88081efb32852230ed55de8.es.png differ diff --git a/translated_images/shapes-to-images.1a309f0ea88dd66fafa4da6d38e88806ce174cc6a88081efb32852230ed55de8.hk.png b/translated_images/shapes-to-images.1a309f0ea88dd66fafa4da6d38e88806ce174cc6a88081efb32852230ed55de8.hk.png new file mode 100644 index 00000000..eee39f7d Binary files /dev/null and b/translated_images/shapes-to-images.1a309f0ea88dd66fafa4da6d38e88806ce174cc6a88081efb32852230ed55de8.hk.png differ diff --git a/translated_images/smarter-thermostat.a75855f15d2d9e63d5da9d7ba5847a987f6c9d98e96e770c203532275194e27d.es.png b/translated_images/smarter-thermostat.a75855f15d2d9e63d5da9d7ba5847a987f6c9d98e96e770c203532275194e27d.es.png new file mode 100644 index 00000000..5a0fb117 Binary files /dev/null and b/translated_images/smarter-thermostat.a75855f15d2d9e63d5da9d7ba5847a987f6c9d98e96e770c203532275194e27d.es.png differ diff --git a/translated_images/smarter-thermostat.a75855f15d2d9e63d5da9d7ba5847a987f6c9d98e96e770c203532275194e27d.hk.png b/translated_images/smarter-thermostat.a75855f15d2d9e63d5da9d7ba5847a987f6c9d98e96e770c203532275194e27d.hk.png new file mode 100644 index 00000000..5a0fb117 Binary files /dev/null and b/translated_images/smarter-thermostat.a75855f15d2d9e63d5da9d7ba5847a987f6c9d98e96e770c203532275194e27d.hk.png differ diff --git a/translated_images/soil-moisture-delay.865f3fae206db01d5f8f100f4f44040215d44a0412dd3450aef7ff7b93b6d273.es.png b/translated_images/soil-moisture-delay.865f3fae206db01d5f8f100f4f44040215d44a0412dd3450aef7ff7b93b6d273.es.png new file mode 100644 index 00000000..27ddbfee Binary files /dev/null and b/translated_images/soil-moisture-delay.865f3fae206db01d5f8f100f4f44040215d44a0412dd3450aef7ff7b93b6d273.es.png differ diff --git a/translated_images/soil-moisture-delay.865f3fae206db01d5f8f100f4f44040215d44a0412dd3450aef7ff7b93b6d273.hk.png b/translated_images/soil-moisture-delay.865f3fae206db01d5f8f100f4f44040215d44a0412dd3450aef7ff7b93b6d273.hk.png new file mode 100644 index 00000000..27ddbfee Binary files /dev/null and b/translated_images/soil-moisture-delay.865f3fae206db01d5f8f100f4f44040215d44a0412dd3450aef7ff7b93b6d273.hk.png differ diff --git a/translated_images/soil-moisture-sensor-in-soil.bfad91002bda5e960f8c51ee64b02ee59b32c8c717e3515a2c945f33e614e403.es.png b/translated_images/soil-moisture-sensor-in-soil.bfad91002bda5e960f8c51ee64b02ee59b32c8c717e3515a2c945f33e614e403.es.png new file mode 100644 index 00000000..ee07bd10 Binary files /dev/null and b/translated_images/soil-moisture-sensor-in-soil.bfad91002bda5e960f8c51ee64b02ee59b32c8c717e3515a2c945f33e614e403.es.png differ diff --git a/translated_images/soil-moisture-sensor-in-soil.bfad91002bda5e960f8c51ee64b02ee59b32c8c717e3515a2c945f33e614e403.hk.png b/translated_images/soil-moisture-sensor-in-soil.bfad91002bda5e960f8c51ee64b02ee59b32c8c717e3515a2c945f33e614e403.hk.png new file mode 100644 index 00000000..ee07bd10 Binary files /dev/null and b/translated_images/soil-moisture-sensor-in-soil.bfad91002bda5e960f8c51ee64b02ee59b32c8c717e3515a2c945f33e614e403.hk.png differ diff --git a/translated_images/soil-moisture-to-voltage-with-reading.681cb3e1f8b68caf5547dbf1415851c82e201edfb78face16fc98da4051ed9b2.es.png b/translated_images/soil-moisture-to-voltage-with-reading.681cb3e1f8b68caf5547dbf1415851c82e201edfb78face16fc98da4051ed9b2.es.png new file mode 100644 index 00000000..37a2464a Binary files /dev/null and b/translated_images/soil-moisture-to-voltage-with-reading.681cb3e1f8b68caf5547dbf1415851c82e201edfb78face16fc98da4051ed9b2.es.png differ diff --git a/translated_images/soil-moisture-to-voltage-with-reading.681cb3e1f8b68caf5547dbf1415851c82e201edfb78face16fc98da4051ed9b2.hk.png b/translated_images/soil-moisture-to-voltage-with-reading.681cb3e1f8b68caf5547dbf1415851c82e201edfb78face16fc98da4051ed9b2.hk.png new file mode 100644 index 00000000..37a2464a Binary files /dev/null and b/translated_images/soil-moisture-to-voltage-with-reading.681cb3e1f8b68caf5547dbf1415851c82e201edfb78face16fc98da4051ed9b2.hk.png differ diff --git a/translated_images/soil-moisture-to-voltage.df86d80cda1587008f312431ed5f79eb6c50c58d4fbc25a6763c5e9127c3106b.es.png b/translated_images/soil-moisture-to-voltage.df86d80cda1587008f312431ed5f79eb6c50c58d4fbc25a6763c5e9127c3106b.es.png new file mode 100644 index 00000000..d852153c Binary files /dev/null and b/translated_images/soil-moisture-to-voltage.df86d80cda1587008f312431ed5f79eb6c50c58d4fbc25a6763c5e9127c3106b.es.png differ diff --git a/translated_images/soil-moisture-to-voltage.df86d80cda1587008f312431ed5f79eb6c50c58d4fbc25a6763c5e9127c3106b.hk.png b/translated_images/soil-moisture-to-voltage.df86d80cda1587008f312431ed5f79eb6c50c58d4fbc25a6763c5e9127c3106b.hk.png new file mode 100644 index 00000000..d852153c Binary files /dev/null and b/translated_images/soil-moisture-to-voltage.df86d80cda1587008f312431ed5f79eb6c50c58d4fbc25a6763c5e9127c3106b.hk.png differ diff --git a/translated_images/soil-moisture-travel.a0e31af222cf14385de5380dfc32c7b8213960965228b8e4f7b7ab7f73b310a3.es.png b/translated_images/soil-moisture-travel.a0e31af222cf14385de5380dfc32c7b8213960965228b8e4f7b7ab7f73b310a3.es.png new file mode 100644 index 00000000..a457ac8d Binary files /dev/null and b/translated_images/soil-moisture-travel.a0e31af222cf14385de5380dfc32c7b8213960965228b8e4f7b7ab7f73b310a3.es.png differ diff --git a/translated_images/soil-moisture-travel.a0e31af222cf14385de5380dfc32c7b8213960965228b8e4f7b7ab7f73b310a3.hk.png b/translated_images/soil-moisture-travel.a0e31af222cf14385de5380dfc32c7b8213960965228b8e4f7b7ab7f73b310a3.hk.png new file mode 100644 index 00000000..a457ac8d Binary files /dev/null and b/translated_images/soil-moisture-travel.a0e31af222cf14385de5380dfc32c7b8213960965228b8e4f7b7ab7f73b310a3.hk.png differ diff --git a/translated_images/spi.297431d6f98b386b4ff88aea44ce9c1e7acfb1ef69c7e4e388a7aa97b6948e24.es.png b/translated_images/spi.297431d6f98b386b4ff88aea44ce9c1e7acfb1ef69c7e4e388a7aa97b6948e24.es.png new file mode 100644 index 00000000..3eccd326 Binary files /dev/null and b/translated_images/spi.297431d6f98b386b4ff88aea44ce9c1e7acfb1ef69c7e4e388a7aa97b6948e24.es.png differ diff --git a/translated_images/spi.297431d6f98b386b4ff88aea44ce9c1e7acfb1ef69c7e4e388a7aa97b6948e24.hk.png b/translated_images/spi.297431d6f98b386b4ff88aea44ce9c1e7acfb1ef69c7e4e388a7aa97b6948e24.hk.png new file mode 100644 index 00000000..3eccd326 Binary files /dev/null and b/translated_images/spi.297431d6f98b386b4ff88aea44ce9c1e7acfb1ef69c7e4e388a7aa97b6948e24.hk.png differ diff --git a/translated_images/sql-database.be160f12bfccefd3ca718a66468c2c4c89c53e5aad4c295324d576da87f9dfdd.es.png b/translated_images/sql-database.be160f12bfccefd3ca718a66468c2c4c89c53e5aad4c295324d576da87f9dfdd.es.png new file mode 100644 index 00000000..49083372 Binary files /dev/null and b/translated_images/sql-database.be160f12bfccefd3ca718a66468c2c4c89c53e5aad4c295324d576da87f9dfdd.es.png differ diff --git a/translated_images/sql-database.be160f12bfccefd3ca718a66468c2c4c89c53e5aad4c295324d576da87f9dfdd.hk.png b/translated_images/sql-database.be160f12bfccefd3ca718a66468c2c4c89c53e5aad4c295324d576da87f9dfdd.hk.png new file mode 100644 index 00000000..49083372 Binary files /dev/null and b/translated_images/sql-database.be160f12bfccefd3ca718a66468c2c4c89c53e5aad4c295324d576da87f9dfdd.hk.png differ diff --git a/translated_images/stock-7-cans-tomato-paste.f86059cc573d7becaa89a0eafb9d2cd7e2fe37405a530fe565990e2333d0e4a1.es.png b/translated_images/stock-7-cans-tomato-paste.f86059cc573d7becaa89a0eafb9d2cd7e2fe37405a530fe565990e2333d0e4a1.es.png new file mode 100644 index 00000000..1b4a94e5 Binary files /dev/null and b/translated_images/stock-7-cans-tomato-paste.f86059cc573d7becaa89a0eafb9d2cd7e2fe37405a530fe565990e2333d0e4a1.es.png differ diff --git a/translated_images/stock-7-cans-tomato-paste.f86059cc573d7becaa89a0eafb9d2cd7e2fe37405a530fe565990e2333d0e4a1.hk.png b/translated_images/stock-7-cans-tomato-paste.f86059cc573d7becaa89a0eafb9d2cd7e2fe37405a530fe565990e2333d0e4a1.hk.png new file mode 100644 index 00000000..1b4a94e5 Binary files /dev/null and b/translated_images/stock-7-cans-tomato-paste.f86059cc573d7becaa89a0eafb9d2cd7e2fe37405a530fe565990e2333d0e4a1.hk.png differ diff --git a/translated_images/stock-rogue-corn.be1f3ada8c4578544641af66671c1711a4c02297f14cc7f503354dae0d30a954.es.png b/translated_images/stock-rogue-corn.be1f3ada8c4578544641af66671c1711a4c02297f14cc7f503354dae0d30a954.es.png new file mode 100644 index 00000000..8589e88f Binary files /dev/null and b/translated_images/stock-rogue-corn.be1f3ada8c4578544641af66671c1711a4c02297f14cc7f503354dae0d30a954.es.png differ diff --git a/translated_images/stock-rogue-corn.be1f3ada8c4578544641af66671c1711a4c02297f14cc7f503354dae0d30a954.hk.png b/translated_images/stock-rogue-corn.be1f3ada8c4578544641af66671c1711a4c02297f14cc7f503354dae0d30a954.hk.png new file mode 100644 index 00000000..8589e88f Binary files /dev/null and b/translated_images/stock-rogue-corn.be1f3ada8c4578544641af66671c1711a4c02297f14cc7f503354dae0d30a954.hk.png differ diff --git a/translated_images/strawberry-with-pump.b410fc72ac6aabad3e28de9775bf2393ead73dcfec6fd8c9bc01cf107ecd171a.es.png b/translated_images/strawberry-with-pump.b410fc72ac6aabad3e28de9775bf2393ead73dcfec6fd8c9bc01cf107ecd171a.es.png new file mode 100644 index 00000000..e1246f56 Binary files /dev/null and b/translated_images/strawberry-with-pump.b410fc72ac6aabad3e28de9775bf2393ead73dcfec6fd8c9bc01cf107ecd171a.es.png differ diff --git a/translated_images/strawberry-with-pump.b410fc72ac6aabad3e28de9775bf2393ead73dcfec6fd8c9bc01cf107ecd171a.hk.png b/translated_images/strawberry-with-pump.b410fc72ac6aabad3e28de9775bf2393ead73dcfec6fd8c9bc01cf107ecd171a.hk.png new file mode 100644 index 00000000..e1246f56 Binary files /dev/null and b/translated_images/strawberry-with-pump.b410fc72ac6aabad3e28de9775bf2393ead73dcfec6fd8c9bc01cf107ecd171a.hk.png differ diff --git a/translated_images/telemetry.21e5d8b97649d2ebeb0f68d4b9691ab2d1f7bd629338e131465aff8a614e4d4a.es.png b/translated_images/telemetry.21e5d8b97649d2ebeb0f68d4b9691ab2d1f7bd629338e131465aff8a614e4d4a.es.png new file mode 100644 index 00000000..db66a52b Binary files /dev/null and b/translated_images/telemetry.21e5d8b97649d2ebeb0f68d4b9691ab2d1f7bd629338e131465aff8a614e4d4a.es.png differ diff --git a/translated_images/telemetry.21e5d8b97649d2ebeb0f68d4b9691ab2d1f7bd629338e131465aff8a614e4d4a.hk.png b/translated_images/telemetry.21e5d8b97649d2ebeb0f68d4b9691ab2d1f7bd629338e131465aff8a614e4d4a.hk.png new file mode 100644 index 00000000..db66a52b Binary files /dev/null and b/translated_images/telemetry.21e5d8b97649d2ebeb0f68d4b9691ab2d1f7bd629338e131465aff8a614e4d4a.hk.png differ diff --git a/translated_images/temperature-as-digital.85004491b977bae1129707df107c0b19fe6fc6374210e9027e04acb34a640c78.es.png b/translated_images/temperature-as-digital.85004491b977bae1129707df107c0b19fe6fc6374210e9027e04acb34a640c78.es.png new file mode 100644 index 00000000..66c76c2f Binary files /dev/null and b/translated_images/temperature-as-digital.85004491b977bae1129707df107c0b19fe6fc6374210e9027e04acb34a640c78.es.png differ diff --git a/translated_images/temperature-as-digital.85004491b977bae1129707df107c0b19fe6fc6374210e9027e04acb34a640c78.hk.png b/translated_images/temperature-as-digital.85004491b977bae1129707df107c0b19fe6fc6374210e9027e04acb34a640c78.hk.png new file mode 100644 index 00000000..66c76c2f Binary files /dev/null and b/translated_images/temperature-as-digital.85004491b977bae1129707df107c0b19fe6fc6374210e9027e04acb34a640c78.hk.png differ diff --git a/translated_images/time-of-flight-banana.079921ad8b1496e4525dc26b4cdc71a076407aba3e72ba113ba2e38febae92c5.es.png b/translated_images/time-of-flight-banana.079921ad8b1496e4525dc26b4cdc71a076407aba3e72ba113ba2e38febae92c5.es.png new file mode 100644 index 00000000..450b824c Binary files /dev/null and b/translated_images/time-of-flight-banana.079921ad8b1496e4525dc26b4cdc71a076407aba3e72ba113ba2e38febae92c5.es.png differ diff --git a/translated_images/time-of-flight-banana.079921ad8b1496e4525dc26b4cdc71a076407aba3e72ba113ba2e38febae92c5.hk.png b/translated_images/time-of-flight-banana.079921ad8b1496e4525dc26b4cdc71a076407aba3e72ba113ba2e38febae92c5.hk.png new file mode 100644 index 00000000..450b824c Binary files /dev/null and b/translated_images/time-of-flight-banana.079921ad8b1496e4525dc26b4cdc71a076407aba3e72ba113ba2e38febae92c5.hk.png differ diff --git a/translated_images/traditional-vs-ml.5c20c169621fa539ca84a2cd9a49f6ff7410b3a6c6b46c97ff2af3f99db3c66b.es.png b/translated_images/traditional-vs-ml.5c20c169621fa539ca84a2cd9a49f6ff7410b3a6c6b46c97ff2af3f99db3c66b.es.png new file mode 100644 index 00000000..615bc7a9 Binary files /dev/null and b/translated_images/traditional-vs-ml.5c20c169621fa539ca84a2cd9a49f6ff7410b3a6c6b46c97ff2af3f99db3c66b.es.png differ diff --git a/translated_images/traditional-vs-ml.5c20c169621fa539ca84a2cd9a49f6ff7410b3a6c6b46c97ff2af3f99db3c66b.hk.png b/translated_images/traditional-vs-ml.5c20c169621fa539ca84a2cd9a49f6ff7410b3a6c6b46c97ff2af3f99db3c66b.hk.png new file mode 100644 index 00000000..615bc7a9 Binary files /dev/null and b/translated_images/traditional-vs-ml.5c20c169621fa539ca84a2cd9a49f6ff7410b3a6c6b46c97ff2af3f99db3c66b.hk.png differ diff --git a/translated_images/translated-smart-timer.08ac20057fdc5c3778ed41cb425dca5d7fbcd4584b6da7b73ca67115a5b8a883.es.png b/translated_images/translated-smart-timer.08ac20057fdc5c3778ed41cb425dca5d7fbcd4584b6da7b73ca67115a5b8a883.es.png new file mode 100644 index 00000000..3c9e2930 Binary files /dev/null and b/translated_images/translated-smart-timer.08ac20057fdc5c3778ed41cb425dca5d7fbcd4584b6da7b73ca67115a5b8a883.es.png differ diff --git a/translated_images/translated-smart-timer.08ac20057fdc5c3778ed41cb425dca5d7fbcd4584b6da7b73ca67115a5b8a883.hk.png b/translated_images/translated-smart-timer.08ac20057fdc5c3778ed41cb425dca5d7fbcd4584b6da7b73ca67115a5b8a883.hk.png new file mode 100644 index 00000000..3c9e2930 Binary files /dev/null and b/translated_images/translated-smart-timer.08ac20057fdc5c3778ed41cb425dca5d7fbcd4584b6da7b73ca67115a5b8a883.hk.png differ diff --git a/translated_images/transpiration.b735aa34e4372e659f76d82527e9ce683f076d56065d0d8fddf13321666f4d80.es.png b/translated_images/transpiration.b735aa34e4372e659f76d82527e9ce683f076d56065d0d8fddf13321666f4d80.es.png new file mode 100644 index 00000000..e4bb0186 Binary files /dev/null and b/translated_images/transpiration.b735aa34e4372e659f76d82527e9ce683f076d56065d0d8fddf13321666f4d80.es.png differ diff --git a/translated_images/transpiration.b735aa34e4372e659f76d82527e9ce683f076d56065d0d8fddf13321666f4d80.hk.png b/translated_images/transpiration.b735aa34e4372e659f76d82527e9ce683f076d56065d0d8fddf13321666f4d80.hk.png new file mode 100644 index 00000000..e4bb0186 Binary files /dev/null and b/translated_images/transpiration.b735aa34e4372e659f76d82527e9ce683f076d56065d0d8fddf13321666f4d80.hk.png differ diff --git a/translated_images/tts-overview.193843cf3f5ee09f8b3371a9fdaeb0f116698a07ca69daaa77158da4800e5453.es.png b/translated_images/tts-overview.193843cf3f5ee09f8b3371a9fdaeb0f116698a07ca69daaa77158da4800e5453.es.png new file mode 100644 index 00000000..91e4cba6 Binary files /dev/null and b/translated_images/tts-overview.193843cf3f5ee09f8b3371a9fdaeb0f116698a07ca69daaa77158da4800e5453.es.png differ diff --git a/translated_images/tts-overview.193843cf3f5ee09f8b3371a9fdaeb0f116698a07ca69daaa77158da4800e5453.hk.png b/translated_images/tts-overview.193843cf3f5ee09f8b3371a9fdaeb0f116698a07ca69daaa77158da4800e5453.hk.png new file mode 100644 index 00000000..91e4cba6 Binary files /dev/null and b/translated_images/tts-overview.193843cf3f5ee09f8b3371a9fdaeb0f116698a07ca69daaa77158da4800e5453.hk.png differ diff --git a/translated_images/uart.d0dbd3fb9e3728c6ee1995c8206f3cdb13cdfd208f13745e8ef6854cab75e421.es.png b/translated_images/uart.d0dbd3fb9e3728c6ee1995c8206f3cdb13cdfd208f13745e8ef6854cab75e421.es.png new file mode 100644 index 00000000..91230d0c Binary files /dev/null and b/translated_images/uart.d0dbd3fb9e3728c6ee1995c8206f3cdb13cdfd208f13745e8ef6854cab75e421.es.png differ diff --git a/translated_images/uart.d0dbd3fb9e3728c6ee1995c8206f3cdb13cdfd208f13745e8ef6854cab75e421.hk.png b/translated_images/uart.d0dbd3fb9e3728c6ee1995c8206f3cdb13cdfd208f13745e8ef6854cab75e421.hk.png new file mode 100644 index 00000000..91230d0c Binary files /dev/null and b/translated_images/uart.d0dbd3fb9e3728c6ee1995c8206f3cdb13cdfd208f13745e8ef6854cab75e421.hk.png differ diff --git a/translated_images/vscode-azure-functions-init-notification.bd19b49229963edb5311fb3a79445ea469424759d2917ee2f2eb6f92d65d5086.es.png b/translated_images/vscode-azure-functions-init-notification.bd19b49229963edb5311fb3a79445ea469424759d2917ee2f2eb6f92d65d5086.es.png new file mode 100644 index 00000000..128cd4a9 Binary files /dev/null and b/translated_images/vscode-azure-functions-init-notification.bd19b49229963edb5311fb3a79445ea469424759d2917ee2f2eb6f92d65d5086.es.png differ diff --git a/translated_images/vscode-azure-functions-init-notification.bd19b49229963edb5311fb3a79445ea469424759d2917ee2f2eb6f92d65d5086.hk.png b/translated_images/vscode-azure-functions-init-notification.bd19b49229963edb5311fb3a79445ea469424759d2917ee2f2eb6f92d65d5086.hk.png new file mode 100644 index 00000000..128cd4a9 Binary files /dev/null and b/translated_images/vscode-azure-functions-init-notification.bd19b49229963edb5311fb3a79445ea469424759d2917ee2f2eb6f92d65d5086.hk.png differ diff --git a/translated_images/vscode-kill-terminal.1cc4de7c6f25ee08f423f0ead714e61d069fac1eb2089e97b8a7bbcb3d45fe5e.es.png b/translated_images/vscode-kill-terminal.1cc4de7c6f25ee08f423f0ead714e61d069fac1eb2089e97b8a7bbcb3d45fe5e.es.png new file mode 100644 index 00000000..8d62d827 Binary files /dev/null and b/translated_images/vscode-kill-terminal.1cc4de7c6f25ee08f423f0ead714e61d069fac1eb2089e97b8a7bbcb3d45fe5e.es.png differ diff --git a/translated_images/vscode-kill-terminal.1cc4de7c6f25ee08f423f0ead714e61d069fac1eb2089e97b8a7bbcb3d45fe5e.hk.png b/translated_images/vscode-kill-terminal.1cc4de7c6f25ee08f423f0ead714e61d069fac1eb2089e97b8a7bbcb3d45fe5e.hk.png new file mode 100644 index 00000000..8d62d827 Binary files /dev/null and b/translated_images/vscode-kill-terminal.1cc4de7c6f25ee08f423f0ead714e61d069fac1eb2089e97b8a7bbcb3d45fe5e.hk.png differ diff --git a/translated_images/vscode-new-file-button.182702340fe6723c8cbb4cfa1a9a9fb0d0a5227643b4e46b91ff67b07a39a92f.es.png b/translated_images/vscode-new-file-button.182702340fe6723c8cbb4cfa1a9a9fb0d0a5227643b4e46b91ff67b07a39a92f.es.png new file mode 100644 index 00000000..a84ab661 Binary files /dev/null and b/translated_images/vscode-new-file-button.182702340fe6723c8cbb4cfa1a9a9fb0d0a5227643b4e46b91ff67b07a39a92f.es.png differ diff --git a/translated_images/vscode-new-file-button.182702340fe6723c8cbb4cfa1a9a9fb0d0a5227643b4e46b91ff67b07a39a92f.hk.png b/translated_images/vscode-new-file-button.182702340fe6723c8cbb4cfa1a9a9fb0d0a5227643b4e46b91ff67b07a39a92f.hk.png new file mode 100644 index 00000000..a84ab661 Binary files /dev/null and b/translated_images/vscode-new-file-button.182702340fe6723c8cbb4cfa1a9a9fb0d0a5227643b4e46b91ff67b07a39a92f.hk.png differ diff --git a/translated_images/vscode-new-terminal.77db8fc0f9cd31824b0e49a201beafe4ae4616d6c7339992cb2819e789b3eff9.es.png b/translated_images/vscode-new-terminal.77db8fc0f9cd31824b0e49a201beafe4ae4616d6c7339992cb2819e789b3eff9.es.png new file mode 100644 index 00000000..4c88d3d3 Binary files /dev/null and b/translated_images/vscode-new-terminal.77db8fc0f9cd31824b0e49a201beafe4ae4616d6c7339992cb2819e789b3eff9.es.png differ diff --git a/translated_images/vscode-new-terminal.77db8fc0f9cd31824b0e49a201beafe4ae4616d6c7339992cb2819e789b3eff9.hk.png b/translated_images/vscode-new-terminal.77db8fc0f9cd31824b0e49a201beafe4ae4616d6c7339992cb2819e789b3eff9.hk.png new file mode 100644 index 00000000..4c88d3d3 Binary files /dev/null and b/translated_images/vscode-new-terminal.77db8fc0f9cd31824b0e49a201beafe4ae4616d6c7339992cb2819e789b3eff9.hk.png differ diff --git a/translated_images/vscode-open-nightlight-remote.d3d2a4011e30d535c4b70084f6e94bf6b5b1327fd8e77affe64465ac151ee766.es.png b/translated_images/vscode-open-nightlight-remote.d3d2a4011e30d535c4b70084f6e94bf6b5b1327fd8e77affe64465ac151ee766.es.png new file mode 100644 index 00000000..bc1895b8 Binary files /dev/null and b/translated_images/vscode-open-nightlight-remote.d3d2a4011e30d535c4b70084f6e94bf6b5b1327fd8e77affe64465ac151ee766.es.png differ diff --git a/translated_images/vscode-open-nightlight-remote.d3d2a4011e30d535c4b70084f6e94bf6b5b1327fd8e77affe64465ac151ee766.hk.png b/translated_images/vscode-open-nightlight-remote.d3d2a4011e30d535c4b70084f6e94bf6b5b1327fd8e77affe64465ac151ee766.hk.png new file mode 100644 index 00000000..bc1895b8 Binary files /dev/null and b/translated_images/vscode-open-nightlight-remote.d3d2a4011e30d535c4b70084f6e94bf6b5b1327fd8e77affe64465ac151ee766.hk.png differ diff --git a/translated_images/vscode-platformio-build-command-palette.7708e7ec7d75d7ee1a0551f42229a321c7e2e4bccac7f1a64df2ed55999f723d.es.png b/translated_images/vscode-platformio-build-command-palette.7708e7ec7d75d7ee1a0551f42229a321c7e2e4bccac7f1a64df2ed55999f723d.es.png new file mode 100644 index 00000000..d8ff3180 Binary files /dev/null and b/translated_images/vscode-platformio-build-command-palette.7708e7ec7d75d7ee1a0551f42229a321c7e2e4bccac7f1a64df2ed55999f723d.es.png differ diff --git a/translated_images/vscode-platformio-build-command-palette.7708e7ec7d75d7ee1a0551f42229a321c7e2e4bccac7f1a64df2ed55999f723d.hk.png b/translated_images/vscode-platformio-build-command-palette.7708e7ec7d75d7ee1a0551f42229a321c7e2e4bccac7f1a64df2ed55999f723d.hk.png new file mode 100644 index 00000000..d8ff3180 Binary files /dev/null and b/translated_images/vscode-platformio-build-command-palette.7708e7ec7d75d7ee1a0551f42229a321c7e2e4bccac7f1a64df2ed55999f723d.hk.png differ diff --git a/translated_images/vscode-platformio-home-open.3f9a41bfd3f4da1c866ec3e69f1675faa30b823b5b58ab58ac88e5df9a85da19.es.png b/translated_images/vscode-platformio-home-open.3f9a41bfd3f4da1c866ec3e69f1675faa30b823b5b58ab58ac88e5df9a85da19.es.png new file mode 100644 index 00000000..06b86a65 Binary files /dev/null and b/translated_images/vscode-platformio-home-open.3f9a41bfd3f4da1c866ec3e69f1675faa30b823b5b58ab58ac88e5df9a85da19.es.png differ diff --git a/translated_images/vscode-platformio-home-open.3f9a41bfd3f4da1c866ec3e69f1675faa30b823b5b58ab58ac88e5df9a85da19.hk.png b/translated_images/vscode-platformio-home-open.3f9a41bfd3f4da1c866ec3e69f1675faa30b823b5b58ab58ac88e5df9a85da19.hk.png new file mode 100644 index 00000000..06b86a65 Binary files /dev/null and b/translated_images/vscode-platformio-home-open.3f9a41bfd3f4da1c866ec3e69f1675faa30b823b5b58ab58ac88e5df9a85da19.hk.png differ diff --git a/translated_images/vscode-platformio-menu.297be26b9733e5c4635d9d8e636e93fed2015809eafb7cc8fd409c37b3ef2ef5.es.png b/translated_images/vscode-platformio-menu.297be26b9733e5c4635d9d8e636e93fed2015809eafb7cc8fd409c37b3ef2ef5.es.png new file mode 100644 index 00000000..ac7aa47a Binary files /dev/null and b/translated_images/vscode-platformio-menu.297be26b9733e5c4635d9d8e636e93fed2015809eafb7cc8fd409c37b3ef2ef5.es.png differ diff --git a/translated_images/vscode-platformio-menu.297be26b9733e5c4635d9d8e636e93fed2015809eafb7cc8fd409c37b3ef2ef5.hk.png b/translated_images/vscode-platformio-menu.297be26b9733e5c4635d9d8e636e93fed2015809eafb7cc8fd409c37b3ef2ef5.hk.png new file mode 100644 index 00000000..ac7aa47a Binary files /dev/null and b/translated_images/vscode-platformio-menu.297be26b9733e5c4635d9d8e636e93fed2015809eafb7cc8fd409c37b3ef2ef5.hk.png differ diff --git a/translated_images/vscode-platformio-nightlight-project-wizard.5c64db4da6037420827c2597507897233457210ee23975711fa2285efdcd0dc7.es.png b/translated_images/vscode-platformio-nightlight-project-wizard.5c64db4da6037420827c2597507897233457210ee23975711fa2285efdcd0dc7.es.png new file mode 100644 index 00000000..20480a22 Binary files /dev/null and b/translated_images/vscode-platformio-nightlight-project-wizard.5c64db4da6037420827c2597507897233457210ee23975711fa2285efdcd0dc7.es.png differ diff --git a/translated_images/vscode-platformio-nightlight-project-wizard.5c64db4da6037420827c2597507897233457210ee23975711fa2285efdcd0dc7.hk.png b/translated_images/vscode-platformio-nightlight-project-wizard.5c64db4da6037420827c2597507897233457210ee23975711fa2285efdcd0dc7.hk.png new file mode 100644 index 00000000..20480a22 Binary files /dev/null and b/translated_images/vscode-platformio-nightlight-project-wizard.5c64db4da6037420827c2597507897233457210ee23975711fa2285efdcd0dc7.hk.png differ diff --git a/translated_images/vscode-platformio-serial-monitor-command-palette.b348ec841b8a1c14af503d6fc0bf73c657c79c9acc12a6b6dd485ce3b5826f48.es.png b/translated_images/vscode-platformio-serial-monitor-command-palette.b348ec841b8a1c14af503d6fc0bf73c657c79c9acc12a6b6dd485ce3b5826f48.es.png new file mode 100644 index 00000000..9d90f435 Binary files /dev/null and b/translated_images/vscode-platformio-serial-monitor-command-palette.b348ec841b8a1c14af503d6fc0bf73c657c79c9acc12a6b6dd485ce3b5826f48.es.png differ diff --git a/translated_images/vscode-platformio-serial-monitor-command-palette.b348ec841b8a1c14af503d6fc0bf73c657c79c9acc12a6b6dd485ce3b5826f48.hk.png b/translated_images/vscode-platformio-serial-monitor-command-palette.b348ec841b8a1c14af503d6fc0bf73c657c79c9acc12a6b6dd485ce3b5826f48.hk.png new file mode 100644 index 00000000..9d90f435 Binary files /dev/null and b/translated_images/vscode-platformio-serial-monitor-command-palette.b348ec841b8a1c14af503d6fc0bf73c657c79c9acc12a6b6dd485ce3b5826f48.hk.png differ diff --git a/translated_images/vscode-platformio-upload-command-palette.9e0f49cf80d1f1c3eb5c6689b8705ad8b89f0374b21698e996fec11e4ed09347.es.png b/translated_images/vscode-platformio-upload-command-palette.9e0f49cf80d1f1c3eb5c6689b8705ad8b89f0374b21698e996fec11e4ed09347.es.png new file mode 100644 index 00000000..27b0ea2c Binary files /dev/null and b/translated_images/vscode-platformio-upload-command-palette.9e0f49cf80d1f1c3eb5c6689b8705ad8b89f0374b21698e996fec11e4ed09347.es.png differ diff --git a/translated_images/vscode-platformio-upload-command-palette.9e0f49cf80d1f1c3eb5c6689b8705ad8b89f0374b21698e996fec11e4ed09347.hk.png b/translated_images/vscode-platformio-upload-command-palette.9e0f49cf80d1f1c3eb5c6689b8705ad8b89f0374b21698e996fec11e4ed09347.hk.png new file mode 100644 index 00000000..27b0ea2c Binary files /dev/null and b/translated_images/vscode-platformio-upload-command-palette.9e0f49cf80d1f1c3eb5c6689b8705ad8b89f0374b21698e996fec11e4ed09347.hk.png differ diff --git a/translated_images/vscode-platformio-welcome-new-button.ba6fc8a4c7b78cc822e1ce47ba29c5db96668cce7c5f4adbfd2f1196422baa26.es.png b/translated_images/vscode-platformio-welcome-new-button.ba6fc8a4c7b78cc822e1ce47ba29c5db96668cce7c5f4adbfd2f1196422baa26.es.png new file mode 100644 index 00000000..3526a6d0 Binary files /dev/null and b/translated_images/vscode-platformio-welcome-new-button.ba6fc8a4c7b78cc822e1ce47ba29c5db96668cce7c5f4adbfd2f1196422baa26.es.png differ diff --git a/translated_images/vscode-platformio-welcome-new-button.ba6fc8a4c7b78cc822e1ce47ba29c5db96668cce7c5f4adbfd2f1196422baa26.hk.png b/translated_images/vscode-platformio-welcome-new-button.ba6fc8a4c7b78cc822e1ce47ba29c5db96668cce7c5f4adbfd2f1196422baa26.hk.png new file mode 100644 index 00000000..3526a6d0 Binary files /dev/null and b/translated_images/vscode-platformio-welcome-new-button.ba6fc8a4c7b78cc822e1ce47ba29c5db96668cce7c5f4adbfd2f1196422baa26.hk.png differ diff --git a/translated_images/vscode-virtual-env.8ba42e04c3d533cf677e16cbe5ed9a3b80f62c6964472dc84b6f940800f0909f.es.png b/translated_images/vscode-virtual-env.8ba42e04c3d533cf677e16cbe5ed9a3b80f62c6964472dc84b6f940800f0909f.es.png new file mode 100644 index 00000000..855d442e Binary files /dev/null and b/translated_images/vscode-virtual-env.8ba42e04c3d533cf677e16cbe5ed9a3b80f62c6964472dc84b6f940800f0909f.es.png differ diff --git a/translated_images/vscode-virtual-env.8ba42e04c3d533cf677e16cbe5ed9a3b80f62c6964472dc84b6f940800f0909f.hk.png b/translated_images/vscode-virtual-env.8ba42e04c3d533cf677e16cbe5ed9a3b80f62c6964472dc84b6f940800f0909f.hk.png new file mode 100644 index 00000000..855d442e Binary files /dev/null and b/translated_images/vscode-virtual-env.8ba42e04c3d533cf677e16cbe5ed9a3b80f62c6964472dc84b6f940800f0909f.hk.png differ diff --git a/translated_images/what-is-azure-video-thumbnail.20174db09e03bbb87d213f928d3cb27410305d2e567e952827de8478dbda959b.es.png b/translated_images/what-is-azure-video-thumbnail.20174db09e03bbb87d213f928d3cb27410305d2e567e952827de8478dbda959b.es.png new file mode 100644 index 00000000..aed3d813 Binary files /dev/null and b/translated_images/what-is-azure-video-thumbnail.20174db09e03bbb87d213f928d3cb27410305d2e567e952827de8478dbda959b.es.png differ diff --git a/translated_images/what-is-azure-video-thumbnail.20174db09e03bbb87d213f928d3cb27410305d2e567e952827de8478dbda959b.hk.png b/translated_images/what-is-azure-video-thumbnail.20174db09e03bbb87d213f928d3cb27410305d2e567e952827de8478dbda959b.hk.png new file mode 100644 index 00000000..aed3d813 Binary files /dev/null and b/translated_images/what-is-azure-video-thumbnail.20174db09e03bbb87d213f928d3cb27410305d2e567e952827de8478dbda959b.hk.png differ diff --git a/translated_images/wio-gps-sensor.19fd52b81ce58095d5deb3d4e5a1fdd88818d76569b00b1f0d740c92dc986525.es.png b/translated_images/wio-gps-sensor.19fd52b81ce58095d5deb3d4e5a1fdd88818d76569b00b1f0d740c92dc986525.es.png new file mode 100644 index 00000000..9bfca6c2 Binary files /dev/null and b/translated_images/wio-gps-sensor.19fd52b81ce58095d5deb3d4e5a1fdd88818d76569b00b1f0d740c92dc986525.es.png differ diff --git a/translated_images/wio-gps-sensor.19fd52b81ce58095d5deb3d4e5a1fdd88818d76569b00b1f0d740c92dc986525.hk.png b/translated_images/wio-gps-sensor.19fd52b81ce58095d5deb3d4e5a1fdd88818d76569b00b1f0d740c92dc986525.hk.png new file mode 100644 index 00000000..9bfca6c2 Binary files /dev/null and b/translated_images/wio-gps-sensor.19fd52b81ce58095d5deb3d4e5a1fdd88818d76569b00b1f0d740c92dc986525.hk.png differ diff --git a/translated_images/wio-hardware-kit.4c70c48b85e4283a1d73e248d87d49587c0cd077eeb69cb3eca803166f63c9a5.es.png b/translated_images/wio-hardware-kit.4c70c48b85e4283a1d73e248d87d49587c0cd077eeb69cb3eca803166f63c9a5.es.png new file mode 100644 index 00000000..0490e302 Binary files /dev/null and b/translated_images/wio-hardware-kit.4c70c48b85e4283a1d73e248d87d49587c0cd077eeb69cb3eca803166f63c9a5.es.png differ diff --git a/translated_images/wio-hardware-kit.4c70c48b85e4283a1d73e248d87d49587c0cd077eeb69cb3eca803166f63c9a5.hk.png b/translated_images/wio-hardware-kit.4c70c48b85e4283a1d73e248d87d49587c0cd077eeb69cb3eca803166f63c9a5.hk.png new file mode 100644 index 00000000..0490e302 Binary files /dev/null and b/translated_images/wio-hardware-kit.4c70c48b85e4283a1d73e248d87d49587c0cd077eeb69cb3eca803166f63c9a5.hk.png differ diff --git a/translated_images/wio-led.265a1897e72d7f21c753257516a4b677d8e30ce2b95fee98189458b3275ba0a6.es.png b/translated_images/wio-led.265a1897e72d7f21c753257516a4b677d8e30ce2b95fee98189458b3275ba0a6.es.png new file mode 100644 index 00000000..676e2378 Binary files /dev/null and b/translated_images/wio-led.265a1897e72d7f21c753257516a4b677d8e30ce2b95fee98189458b3275ba0a6.es.png differ diff --git a/translated_images/wio-led.265a1897e72d7f21c753257516a4b677d8e30ce2b95fee98189458b3275ba0a6.hk.png b/translated_images/wio-led.265a1897e72d7f21c753257516a4b677d8e30ce2b95fee98189458b3275ba0a6.hk.png new file mode 100644 index 00000000..676e2378 Binary files /dev/null and b/translated_images/wio-led.265a1897e72d7f21c753257516a4b677d8e30ce2b95fee98189458b3275ba0a6.hk.png differ diff --git a/translated_images/wio-light-sensor.b1f529f3c95f51654f2e2c1d2d4b55fe547d189f588c974f5c2462c728133840.es.png b/translated_images/wio-light-sensor.b1f529f3c95f51654f2e2c1d2d4b55fe547d189f588c974f5c2462c728133840.es.png new file mode 100644 index 00000000..280e18c3 Binary files /dev/null and b/translated_images/wio-light-sensor.b1f529f3c95f51654f2e2c1d2d4b55fe547d189f588c974f5c2462c728133840.es.png differ diff --git a/translated_images/wio-light-sensor.b1f529f3c95f51654f2e2c1d2d4b55fe547d189f588c974f5c2462c728133840.hk.png b/translated_images/wio-light-sensor.b1f529f3c95f51654f2e2c1d2d4b55fe547d189f588c974f5c2462c728133840.hk.png new file mode 100644 index 00000000..280e18c3 Binary files /dev/null and b/translated_images/wio-light-sensor.b1f529f3c95f51654f2e2c1d2d4b55fe547d189f588c974f5c2462c728133840.hk.png differ diff --git a/translated_images/wio-mic.3f8c843dbe8ad917424037a93e3d25c62634add00a04dd8e091317b5a7a90088.es.png b/translated_images/wio-mic.3f8c843dbe8ad917424037a93e3d25c62634add00a04dd8e091317b5a7a90088.es.png new file mode 100644 index 00000000..bb70a905 Binary files /dev/null and b/translated_images/wio-mic.3f8c843dbe8ad917424037a93e3d25c62634add00a04dd8e091317b5a7a90088.es.png differ diff --git a/translated_images/wio-mic.3f8c843dbe8ad917424037a93e3d25c62634add00a04dd8e091317b5a7a90088.hk.png b/translated_images/wio-mic.3f8c843dbe8ad917424037a93e3d25c62634add00a04dd8e091317b5a7a90088.hk.png new file mode 100644 index 00000000..bb70a905 Binary files /dev/null and b/translated_images/wio-mic.3f8c843dbe8ad917424037a93e3d25c62634add00a04dd8e091317b5a7a90088.hk.png differ diff --git a/translated_images/wio-relay-and-soil-moisture-sensor.ed722202d42babe0be5f4518cf13e8c2c81e8df21d37839266cbdb60cf30172d.es.png b/translated_images/wio-relay-and-soil-moisture-sensor.ed722202d42babe0be5f4518cf13e8c2c81e8df21d37839266cbdb60cf30172d.es.png new file mode 100644 index 00000000..c0860d6e Binary files /dev/null and b/translated_images/wio-relay-and-soil-moisture-sensor.ed722202d42babe0be5f4518cf13e8c2c81e8df21d37839266cbdb60cf30172d.es.png differ diff --git a/translated_images/wio-relay-and-soil-moisture-sensor.ed722202d42babe0be5f4518cf13e8c2c81e8df21d37839266cbdb60cf30172d.hk.png b/translated_images/wio-relay-and-soil-moisture-sensor.ed722202d42babe0be5f4518cf13e8c2c81e8df21d37839266cbdb60cf30172d.hk.png new file mode 100644 index 00000000..c0860d6e Binary files /dev/null and b/translated_images/wio-relay-and-soil-moisture-sensor.ed722202d42babe0be5f4518cf13e8c2c81e8df21d37839266cbdb60cf30172d.hk.png differ diff --git a/translated_images/wio-respeaker-hat.bd54917d446e6f6f142f9371ea52c12fd708873986bf46191208a151cd929bad.es.png b/translated_images/wio-respeaker-hat.bd54917d446e6f6f142f9371ea52c12fd708873986bf46191208a151cd929bad.es.png new file mode 100644 index 00000000..9a34d708 Binary files /dev/null and b/translated_images/wio-respeaker-hat.bd54917d446e6f6f142f9371ea52c12fd708873986bf46191208a151cd929bad.es.png differ diff --git a/translated_images/wio-respeaker-hat.bd54917d446e6f6f142f9371ea52c12fd708873986bf46191208a151cd929bad.hk.png b/translated_images/wio-respeaker-hat.bd54917d446e6f6f142f9371ea52c12fd708873986bf46191208a151cd929bad.hk.png new file mode 100644 index 00000000..9a34d708 Binary files /dev/null and b/translated_images/wio-respeaker-hat.bd54917d446e6f6f142f9371ea52c12fd708873986bf46191208a151cd929bad.hk.png differ diff --git a/translated_images/wio-respeaker-wiring-0.767f80aa6508103880d256cdf99ee7219e190db257c7261e4aec219759dc67b9.es.png b/translated_images/wio-respeaker-wiring-0.767f80aa6508103880d256cdf99ee7219e190db257c7261e4aec219759dc67b9.es.png new file mode 100644 index 00000000..2c683d8b Binary files /dev/null and b/translated_images/wio-respeaker-wiring-0.767f80aa6508103880d256cdf99ee7219e190db257c7261e4aec219759dc67b9.es.png differ diff --git a/translated_images/wio-respeaker-wiring-0.767f80aa6508103880d256cdf99ee7219e190db257c7261e4aec219759dc67b9.hk.png b/translated_images/wio-respeaker-wiring-0.767f80aa6508103880d256cdf99ee7219e190db257c7261e4aec219759dc67b9.hk.png new file mode 100644 index 00000000..2c683d8b Binary files /dev/null and b/translated_images/wio-respeaker-wiring-0.767f80aa6508103880d256cdf99ee7219e190db257c7261e4aec219759dc67b9.hk.png differ diff --git a/translated_images/wio-respeaker-wiring-1.8d894727f2ba24004824ee5e06b83b6d10952550003a3efb603182121521b0ef.es.png b/translated_images/wio-respeaker-wiring-1.8d894727f2ba24004824ee5e06b83b6d10952550003a3efb603182121521b0ef.es.png new file mode 100644 index 00000000..1ba4c5b0 Binary files /dev/null and b/translated_images/wio-respeaker-wiring-1.8d894727f2ba24004824ee5e06b83b6d10952550003a3efb603182121521b0ef.es.png differ diff --git a/translated_images/wio-respeaker-wiring-1.8d894727f2ba24004824ee5e06b83b6d10952550003a3efb603182121521b0ef.hk.png b/translated_images/wio-respeaker-wiring-1.8d894727f2ba24004824ee5e06b83b6d10952550003a3efb603182121521b0ef.hk.png new file mode 100644 index 00000000..1ba4c5b0 Binary files /dev/null and b/translated_images/wio-respeaker-wiring-1.8d894727f2ba24004824ee5e06b83b6d10952550003a3efb603182121521b0ef.hk.png differ diff --git a/translated_images/wio-respeaker-wiring-2.329e1cbd306e754f8ffe56f9294794f4a8fa123860d76067a79e9ea385d1bf56.es.png b/translated_images/wio-respeaker-wiring-2.329e1cbd306e754f8ffe56f9294794f4a8fa123860d76067a79e9ea385d1bf56.es.png new file mode 100644 index 00000000..93aa3743 Binary files /dev/null and b/translated_images/wio-respeaker-wiring-2.329e1cbd306e754f8ffe56f9294794f4a8fa123860d76067a79e9ea385d1bf56.es.png differ diff --git a/translated_images/wio-respeaker-wiring-2.329e1cbd306e754f8ffe56f9294794f4a8fa123860d76067a79e9ea385d1bf56.hk.png b/translated_images/wio-respeaker-wiring-2.329e1cbd306e754f8ffe56f9294794f4a8fa123860d76067a79e9ea385d1bf56.hk.png new file mode 100644 index 00000000..93aa3743 Binary files /dev/null and b/translated_images/wio-respeaker-wiring-2.329e1cbd306e754f8ffe56f9294794f4a8fa123860d76067a79e9ea385d1bf56.hk.png differ diff --git a/translated_images/wio-respeaker-wiring-3.75b0be447e2fa9307a6a954f9ae8a71b77e39ada6a5ef1a059d341dc850fd90c.es.png b/translated_images/wio-respeaker-wiring-3.75b0be447e2fa9307a6a954f9ae8a71b77e39ada6a5ef1a059d341dc850fd90c.es.png new file mode 100644 index 00000000..3089e5e1 Binary files /dev/null and b/translated_images/wio-respeaker-wiring-3.75b0be447e2fa9307a6a954f9ae8a71b77e39ada6a5ef1a059d341dc850fd90c.es.png differ diff --git a/translated_images/wio-respeaker-wiring-3.75b0be447e2fa9307a6a954f9ae8a71b77e39ada6a5ef1a059d341dc850fd90c.hk.png b/translated_images/wio-respeaker-wiring-3.75b0be447e2fa9307a6a954f9ae8a71b77e39ada6a5ef1a059d341dc850fd90c.hk.png new file mode 100644 index 00000000..3089e5e1 Binary files /dev/null and b/translated_images/wio-respeaker-wiring-3.75b0be447e2fa9307a6a954f9ae8a71b77e39ada6a5ef1a059d341dc850fd90c.hk.png differ diff --git a/translated_images/wio-respeaker-wiring-4.aa9cd434d8779437de720cba2719d83992413caed1b620b6148f6c8924889afb.es.png b/translated_images/wio-respeaker-wiring-4.aa9cd434d8779437de720cba2719d83992413caed1b620b6148f6c8924889afb.es.png new file mode 100644 index 00000000..53468420 Binary files /dev/null and b/translated_images/wio-respeaker-wiring-4.aa9cd434d8779437de720cba2719d83992413caed1b620b6148f6c8924889afb.es.png differ diff --git a/translated_images/wio-respeaker-wiring-4.aa9cd434d8779437de720cba2719d83992413caed1b620b6148f6c8924889afb.hk.png b/translated_images/wio-respeaker-wiring-4.aa9cd434d8779437de720cba2719d83992413caed1b620b6148f6c8924889afb.hk.png new file mode 100644 index 00000000..53468420 Binary files /dev/null and b/translated_images/wio-respeaker-wiring-4.aa9cd434d8779437de720cba2719d83992413caed1b620b6148f6c8924889afb.hk.png differ diff --git a/translated_images/wio-respeaker-wiring-5.af117c20acf622f3cd656ccd8f4053f8845d6aaa3af164d24cb7dbd54a4bb470.es.png b/translated_images/wio-respeaker-wiring-5.af117c20acf622f3cd656ccd8f4053f8845d6aaa3af164d24cb7dbd54a4bb470.es.png new file mode 100644 index 00000000..003dc174 Binary files /dev/null and b/translated_images/wio-respeaker-wiring-5.af117c20acf622f3cd656ccd8f4053f8845d6aaa3af164d24cb7dbd54a4bb470.es.png differ diff --git a/translated_images/wio-respeaker-wiring-5.af117c20acf622f3cd656ccd8f4053f8845d6aaa3af164d24cb7dbd54a4bb470.hk.png b/translated_images/wio-respeaker-wiring-5.af117c20acf622f3cd656ccd8f4053f8845d6aaa3af164d24cb7dbd54a4bb470.hk.png new file mode 100644 index 00000000..003dc174 Binary files /dev/null and b/translated_images/wio-respeaker-wiring-5.af117c20acf622f3cd656ccd8f4053f8845d6aaa3af164d24cb7dbd54a4bb470.hk.png differ diff --git a/translated_images/wio-sd-card.acdcbe322fa4ee7f8f9c8cc015b3263964bb26ab5c7e25b41747988cc5280d64.es.png b/translated_images/wio-sd-card.acdcbe322fa4ee7f8f9c8cc015b3263964bb26ab5c7e25b41747988cc5280d64.es.png new file mode 100644 index 00000000..3c0d2f87 Binary files /dev/null and b/translated_images/wio-sd-card.acdcbe322fa4ee7f8f9c8cc015b3263964bb26ab5c7e25b41747988cc5280d64.es.png differ diff --git a/translated_images/wio-sd-card.acdcbe322fa4ee7f8f9c8cc015b3263964bb26ab5c7e25b41747988cc5280d64.hk.png b/translated_images/wio-sd-card.acdcbe322fa4ee7f8f9c8cc015b3263964bb26ab5c7e25b41747988cc5280d64.hk.png new file mode 100644 index 00000000..3c0d2f87 Binary files /dev/null and b/translated_images/wio-sd-card.acdcbe322fa4ee7f8f9c8cc015b3263964bb26ab5c7e25b41747988cc5280d64.hk.png differ diff --git a/translated_images/wio-soil-moisture-sensor.46919b61c3f6cb7497662251b29038ee0e57a4c8b9d071feb996c3b0d7f65aaf.es.png b/translated_images/wio-soil-moisture-sensor.46919b61c3f6cb7497662251b29038ee0e57a4c8b9d071feb996c3b0d7f65aaf.es.png new file mode 100644 index 00000000..56f285f2 Binary files /dev/null and b/translated_images/wio-soil-moisture-sensor.46919b61c3f6cb7497662251b29038ee0e57a4c8b9d071feb996c3b0d7f65aaf.es.png differ diff --git a/translated_images/wio-soil-moisture-sensor.46919b61c3f6cb7497662251b29038ee0e57a4c8b9d071feb996c3b0d7f65aaf.hk.png b/translated_images/wio-soil-moisture-sensor.46919b61c3f6cb7497662251b29038ee0e57a4c8b9d071feb996c3b0d7f65aaf.hk.png new file mode 100644 index 00000000..56f285f2 Binary files /dev/null and b/translated_images/wio-soil-moisture-sensor.46919b61c3f6cb7497662251b29038ee0e57a4c8b9d071feb996c3b0d7f65aaf.hk.png differ diff --git a/translated_images/wio-temperature-sensor.2934928f38c7f79a68d24879d2c8986c78244696f931e2e33c293f426ecdc0ad.es.png b/translated_images/wio-temperature-sensor.2934928f38c7f79a68d24879d2c8986c78244696f931e2e33c293f426ecdc0ad.es.png new file mode 100644 index 00000000..ec8bbe2f Binary files /dev/null and b/translated_images/wio-temperature-sensor.2934928f38c7f79a68d24879d2c8986c78244696f931e2e33c293f426ecdc0ad.es.png differ diff --git a/translated_images/wio-temperature-sensor.2934928f38c7f79a68d24879d2c8986c78244696f931e2e33c293f426ecdc0ad.hk.png b/translated_images/wio-temperature-sensor.2934928f38c7f79a68d24879d2c8986c78244696f931e2e33c293f426ecdc0ad.hk.png new file mode 100644 index 00000000..ec8bbe2f Binary files /dev/null and b/translated_images/wio-temperature-sensor.2934928f38c7f79a68d24879d2c8986c78244696f931e2e33c293f426ecdc0ad.hk.png differ diff --git a/translated_images/wio-terminal-c-button.73df3cb1c1445ea07ee98316af0e7925fcb43135df0abed58d3d4822b2589c3b.es.png b/translated_images/wio-terminal-c-button.73df3cb1c1445ea07ee98316af0e7925fcb43135df0abed58d3d4822b2589c3b.es.png new file mode 100644 index 00000000..bbaae894 Binary files /dev/null and b/translated_images/wio-terminal-c-button.73df3cb1c1445ea07ee98316af0e7925fcb43135df0abed58d3d4822b2589c3b.es.png differ diff --git a/translated_images/wio-terminal-c-button.73df3cb1c1445ea07ee98316af0e7925fcb43135df0abed58d3d4822b2589c3b.hk.png b/translated_images/wio-terminal-c-button.73df3cb1c1445ea07ee98316af0e7925fcb43135df0abed58d3d4822b2589c3b.hk.png new file mode 100644 index 00000000..bbaae894 Binary files /dev/null and b/translated_images/wio-terminal-c-button.73df3cb1c1445ea07ee98316af0e7925fcb43135df0abed58d3d4822b2589c3b.hk.png differ diff --git a/translated_images/wio-terminal-pin-sticker.b90b1535937b84bd00d853f0004aea74fac2aec04b43f14b887796b2633f855e.es.png b/translated_images/wio-terminal-pin-sticker.b90b1535937b84bd00d853f0004aea74fac2aec04b43f14b887796b2633f855e.es.png new file mode 100644 index 00000000..ef71f6da Binary files /dev/null and b/translated_images/wio-terminal-pin-sticker.b90b1535937b84bd00d853f0004aea74fac2aec04b43f14b887796b2633f855e.es.png differ diff --git a/translated_images/wio-terminal-pin-sticker.b90b1535937b84bd00d853f0004aea74fac2aec04b43f14b887796b2633f855e.hk.png b/translated_images/wio-terminal-pin-sticker.b90b1535937b84bd00d853f0004aea74fac2aec04b43f14b887796b2633f855e.hk.png new file mode 100644 index 00000000..ef71f6da Binary files /dev/null and b/translated_images/wio-terminal-pin-sticker.b90b1535937b84bd00d853f0004aea74fac2aec04b43f14b887796b2633f855e.hk.png differ diff --git a/translated_images/wio-terminal.b8299ee16587db9aa9e05fabf9721bccd9eb8fb541b7c1a8267241282d81b603.es.png b/translated_images/wio-terminal.b8299ee16587db9aa9e05fabf9721bccd9eb8fb541b7c1a8267241282d81b603.es.png new file mode 100644 index 00000000..4e9390eb Binary files /dev/null and b/translated_images/wio-terminal.b8299ee16587db9aa9e05fabf9721bccd9eb8fb541b7c1a8267241282d81b603.es.png differ diff --git a/translated_images/wio-terminal.b8299ee16587db9aa9e05fabf9721bccd9eb8fb541b7c1a8267241282d81b603.hk.png b/translated_images/wio-terminal.b8299ee16587db9aa9e05fabf9721bccd9eb8fb541b7c1a8267241282d81b603.hk.png new file mode 100644 index 00000000..4e9390eb Binary files /dev/null and b/translated_images/wio-terminal.b8299ee16587db9aa9e05fabf9721bccd9eb8fb541b7c1a8267241282d81b603.hk.png differ diff --git a/translated_images/wio-time-of-flight-sensor.c4c182131d2ea73df67febd004dc0313d271013d016be9c47e7da4d77c6c20a8.es.png b/translated_images/wio-time-of-flight-sensor.c4c182131d2ea73df67febd004dc0313d271013d016be9c47e7da4d77c6c20a8.es.png new file mode 100644 index 00000000..16d7af80 Binary files /dev/null and b/translated_images/wio-time-of-flight-sensor.c4c182131d2ea73df67febd004dc0313d271013d016be9c47e7da4d77c6c20a8.es.png differ diff --git a/translated_images/wio-time-of-flight-sensor.c4c182131d2ea73df67febd004dc0313d271013d016be9c47e7da4d77c6c20a8.hk.png b/translated_images/wio-time-of-flight-sensor.c4c182131d2ea73df67febd004dc0313d271013d016be9c47e7da4d77c6c20a8.hk.png new file mode 100644 index 00000000..16d7af80 Binary files /dev/null and b/translated_images/wio-time-of-flight-sensor.c4c182131d2ea73df67febd004dc0313d271013d016be9c47e7da4d77c6c20a8.hk.png differ diff --git a/translations/de/2-farm/lessons/1-predict-plant-growth/code-notebook/gdd.ipynb b/translations/de/2-farm/lessons/1-predict-plant-growth/code-notebook/gdd.ipynb new file mode 100644 index 00000000..d0fd2a43 --- /dev/null +++ b/translations/de/2-farm/lessons/1-predict-plant-growth/code-notebook/gdd.ipynb @@ -0,0 +1,167 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Wachstumsgradtage\n", + "\n", + "Dieses Notebook lädt Temperaturdaten aus einer CSV-Datei und analysiert sie. Es erstellt Diagramme der Temperaturen, zeigt die höchsten und niedrigsten Werte für jeden Tag und berechnet die GDD.\n", + "\n", + "So verwenden Sie dieses Notebook:\n", + "\n", + "* Kopieren Sie die Datei `temperature.csv` in denselben Ordner wie dieses Notebook.\n", + "* Führen Sie alle Zellen mit der **▶︎ Run**-Schaltfläche oben aus. Dadurch wird die ausgewählte Zelle ausgeführt und anschließend zur nächsten gewechselt.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Im folgenden Feld setzen Sie `base_temperature` auf die Basistemperatur der Anlage.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "base_temperature = 10" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Die CSV-Datei muss nun mit pandas geladen werden\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Read the temperature CSV file\n", + "df = pd.read_csv('temperature.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure(figsize=(20, 10))\n", + "plt.plot(df['date'], df['temperature'])\n", + "plt.xticks(rotation='vertical');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Sobald die Daten gelesen wurden, können sie nach der Spalte `date` gruppiert und die minimalen und maximalen Temperaturen für jedes Datum extrahiert werden.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Convert datetimes to pure dates so we can group by the date\n", + "df['date'] = pd.to_datetime(df['date']).dt.date\n", + "\n", + "# Group the data by date so it can be analyzed by date\n", + "data_by_date = df.groupby('date')\n", + "\n", + "# Get the minimum and maximum temperatures for each date\n", + "min_by_date = data_by_date.min()\n", + "max_by_date = data_by_date.max()\n", + "\n", + "# Join the min and max temperatures into one dataframe and flatten it\n", + "min_max_by_date = min_by_date.join(max_by_date, on='date', lsuffix='_min', rsuffix='_max')\n", + "min_max_by_date = min_max_by_date.reset_index()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Die GDD kann mit der standardmäßigen GDD-Gleichung berechnet werden\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_gdd(row):\n", + " return ((row['temperature_max'] + row['temperature_min']) / 2) - base_temperature\n", + "\n", + "# Calculate the GDD for each row\n", + "min_max_by_date['gdd'] = min_max_by_date.apply (lambda row: calculate_gdd(row), axis=1)\n", + "\n", + "# Print the results\n", + "print(min_max_by_date[['date', 'gdd']].to_string(index=False))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n---\n\n**Haftungsausschluss**: \nDieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.1" + }, + "metadata": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + }, + "coopTranslator": { + "original_hash": "8fcf954f6042f0bf3601a2c836a09574", + "translation_date": "2025-08-26T15:59:48+00:00", + "source_file": "2-farm/lessons/1-predict-plant-growth/code-notebook/gdd.ipynb", + "language_code": "de" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/translations/es/1-getting-started/README.md b/translations/es/1-getting-started/README.md new file mode 100644 index 00000000..481fa2a0 --- /dev/null +++ b/translations/es/1-getting-started/README.md @@ -0,0 +1,30 @@ + +# Comenzando con IoT + +En esta sección del plan de estudios, se te presentará el Internet de las Cosas y aprenderás los conceptos básicos, incluyendo la creación de tu primer proyecto IoT de 'Hola Mundo' conectado a la nube. Este proyecto consiste en una luz nocturna que se enciende a medida que los niveles de luz medidos por un sensor disminuyen. + +![El LED conectado al WIO encendiéndose y apagándose a medida que cambian los niveles de luz](../../../images/wio-running-assignment-1-1.gif) + +## Temas + +1. [Introducción a IoT](lessons/1-introduction-to-iot/README.md) +1. [Un análisis más profundo de IoT](lessons/2-deeper-dive/README.md) +1. [Interactúa con el mundo físico usando sensores y actuadores](lessons/3-sensors-and-actuators/README.md) +1. [Conecta tu dispositivo a Internet](lessons/4-connect-internet/README.md) + +## Créditos + +Todas las lecciones fueron escritas con ♥️ por [Jim Bennett](https://GitHub.com/JimBobBennett) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/1-introduction-to-iot/README.md b/translations/es/1-getting-started/lessons/1-introduction-to-iot/README.md new file mode 100644 index 00000000..61fd3a08 --- /dev/null +++ b/translations/es/1-getting-started/lessons/1-introduction-to-iot/README.md @@ -0,0 +1,242 @@ + +# Introducción a IoT + +![Un resumen visual de esta lección](../../../../../translated_images/lesson-1.2606670fa61ee904687da5d6fa4e726639d524d064c895117da1b95b9ff6251d.es.jpg) + +> Sketchnote por [Nitya Narasimhan](https://github.com/nitya). Haz clic en la imagen para una versión más grande. + +Esta lección fue impartida como parte de la serie [Hello IoT](https://youtube.com/playlist?list=PLmsFUfdnGr3xRts0TIwyaHyQuHaNQcb6-) del [Microsoft Reactor](https://developer.microsoft.com/reactor/?WT.mc_id=academic-17441-jabenn). La lección se presentó en 2 videos: una clase de 1 hora y una sesión de preguntas y respuestas de 1 hora para profundizar en partes de la lección y responder preguntas. + +[![Lección 1: Introducción a IoT](https://img.youtube.com/vi/bVFfcYh6UBw/0.jpg)](https://youtu.be/bVFfcYh6UBw) + +[![Lección 1: Introducción a IoT - Horas de oficina](https://img.youtube.com/vi/YI772q5v3yI/0.jpg)](https://youtu.be/YI772q5v3yI) + +> 🎥 Haz clic en las imágenes de arriba para ver los videos + +## Cuestionario previo a la lección + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/1) + +## Introducción + +Esta lección cubre algunos de los temas introductorios sobre el Internet de las Cosas (IoT) y te guía en la configuración de tu hardware. + +En esta lección cubriremos: + +* [¿Qué es el 'Internet de las Cosas'?](../../../../../1-getting-started/lessons/1-introduction-to-iot) +* [Dispositivos IoT](../../../../../1-getting-started/lessons/1-introduction-to-iot) +* [Configura tu dispositivo](../../../../../1-getting-started/lessons/1-introduction-to-iot) +* [Aplicaciones de IoT](../../../../../1-getting-started/lessons/1-introduction-to-iot) +* [Ejemplos de dispositivos IoT que podrías tener a tu alrededor](../../../../../1-getting-started/lessons/1-introduction-to-iot) + +## ¿Qué es el 'Internet de las Cosas'? + +El término 'Internet de las Cosas' fue acuñado por [Kevin Ashton](https://wikipedia.org/wiki/Kevin_Ashton) en 1999 para referirse a la conexión de Internet con el mundo físico a través de sensores. Desde entonces, el término se ha utilizado para describir cualquier dispositivo que interactúe con el mundo físico que lo rodea, ya sea recopilando datos de sensores o proporcionando interacciones en el mundo real a través de actuadores (dispositivos que hacen algo como encender un interruptor o iluminar un LED), generalmente conectados a otros dispositivos o a Internet. + +> **Sensores** recopilan información del mundo, como medir velocidad, temperatura o ubicación. +> +> **Actuadores** convierten señales eléctricas en interacciones del mundo real, como activar un interruptor, encender luces, emitir sonidos o enviar señales de control a otro hardware, por ejemplo, para encender un enchufe. + +IoT como área tecnológica abarca más que solo dispositivos: incluye servicios en la nube que pueden procesar los datos de los sensores o enviar solicitudes a actuadores conectados a dispositivos IoT. También incluye dispositivos que no tienen o no necesitan conectividad a Internet, a menudo denominados dispositivos de borde. Estos dispositivos pueden procesar y responder a datos de sensores por sí mismos, generalmente utilizando modelos de IA entrenados en la nube. + +IoT es un campo tecnológico en rápido crecimiento. Se estima que para finales de 2020, había 30 mil millones de dispositivos IoT desplegados y conectados a Internet. Mirando al futuro, se estima que para 2025, los dispositivos IoT recopilarán casi 80 zettabytes de datos, o 80 billones de gigabytes. ¡Eso es una cantidad enorme de datos! + +![Un gráfico que muestra dispositivos IoT activos a lo largo del tiempo, con una tendencia ascendente de menos de 5 mil millones en 2015 a más de 30 mil millones en 2025](../../../../../images/connected-iot-devices.svg) + +✅ Investiga un poco: ¿Cuánta de la información generada por los dispositivos IoT se utiliza realmente y cuánta se desperdicia? ¿Por qué se ignora tanta información? + +Estos datos son clave para el éxito de IoT. Para ser un desarrollador exitoso de IoT, necesitas entender qué datos necesitas recopilar, cómo recopilarlos, cómo tomar decisiones basadas en ellos y cómo usar esas decisiones para interactuar con el mundo físico si es necesario. + +## Dispositivos IoT + +La **T** en IoT significa **Things** (Cosas): dispositivos que interactúan con el mundo físico que los rodea, ya sea recopilando datos de sensores o proporcionando interacciones en el mundo real a través de actuadores. + +Los dispositivos para uso comercial o de producción, como rastreadores de actividad física para consumidores o controladores de máquinas industriales, suelen ser hechos a medida. Utilizan placas de circuito personalizadas, tal vez incluso procesadores personalizados, diseñados para satisfacer las necesidades de una tarea específica, ya sea ser lo suficientemente pequeños para caber en una muñeca o lo suficientemente resistentes para trabajar en un entorno de fábrica con altas temperaturas, estrés o vibraciones. + +Como desarrollador que aprende sobre IoT o crea un prototipo de dispositivo, necesitarás comenzar con un kit de desarrollo. Estos son dispositivos IoT de propósito general diseñados para desarrolladores, a menudo con características que no tendrías en un dispositivo de producción, como un conjunto de pines externos para conectar sensores o actuadores, hardware para depuración o recursos adicionales que agregarían costos innecesarios en una producción a gran escala. + +Estos kits de desarrollo generalmente se dividen en dos categorías: microcontroladores y computadoras de placa única. Estos se presentarán aquí, y entraremos en más detalle en la próxima lección. + +> 💁 Tu teléfono también puede considerarse un dispositivo IoT de propósito general, con sensores y actuadores integrados, y diferentes aplicaciones que utilizan los sensores y actuadores de diferentes maneras con diferentes servicios en la nube. Incluso puedes encontrar algunos tutoriales de IoT que usan una aplicación de teléfono como dispositivo IoT. + +### Microcontroladores + +Un microcontrolador (también conocido como MCU, por sus siglas en inglés de microcontroller unit) es una pequeña computadora que consta de: + +🧠 Una o más unidades centrales de procesamiento (CPUs): el 'cerebro' del microcontrolador que ejecuta tu programa. + +💾 Memoria (RAM y memoria de programa): donde se almacenan tu programa, datos y variables. + +🔌 Conexiones de entrada/salida (I/O) programables: para comunicarse con periféricos externos (dispositivos conectados) como sensores y actuadores. + +Los microcontroladores son dispositivos de computación de bajo costo, con precios promedio para los utilizados en hardware personalizado que bajan a alrededor de US$0.50, y algunos dispositivos tan baratos como US$0.03. Los kits de desarrollo pueden comenzar desde tan solo US$4, con costos que aumentan a medida que se agregan más características. El [Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html), un kit de desarrollo de microcontroladores de [Seeed studios](https://www.seeedstudio.com) que tiene sensores, actuadores, WiFi y una pantalla, cuesta alrededor de US$30. + +![Un Wio Terminal](../../../../../translated_images/wio-terminal.b8299ee16587db9aa9e05fabf9721bccd9eb8fb541b7c1a8267241282d81b603.es.png) + +> 💁 Al buscar microcontroladores en Internet, ten cuidado al buscar el término **MCU**, ya que esto traerá muchos resultados relacionados con el Universo Cinematográfico de Marvel, no con microcontroladores. + +Los microcontroladores están diseñados para ser programados para realizar un número limitado de tareas muy específicas, en lugar de ser computadoras de propósito general como las PC o Mac. Excepto en escenarios muy específicos, no puedes conectar un monitor, teclado y ratón y usarlos para tareas generales. + +Los kits de desarrollo de microcontroladores generalmente vienen con sensores y actuadores adicionales integrados. La mayoría de las placas tendrán uno o más LEDs que puedes programar, junto con otros dispositivos como conectores estándar para agregar más sensores o actuadores utilizando los ecosistemas de varios fabricantes o sensores integrados (generalmente los más populares, como sensores de temperatura). Algunos microcontroladores tienen conectividad inalámbrica integrada, como Bluetooth o WiFi, o tienen microcontroladores adicionales en la placa para agregar esta conectividad. + +> 💁 Los microcontroladores generalmente se programan en C/C++. + +### Computadoras de placa única + +Una computadora de placa única es un pequeño dispositivo de computación que tiene todos los elementos de una computadora completa contenidos en una sola placa pequeña. Estos son dispositivos con especificaciones cercanas a una PC o Mac de escritorio o portátil, ejecutan un sistema operativo completo, pero son pequeños, consumen menos energía y son sustancialmente más baratos. + +![Una Raspberry Pi 4](../../../../../translated_images/raspberry-pi-4.fd4590d308c3d456db1327e86b395ddcd735513267aafd4879ea2785f7792eac.es.jpg) + +La Raspberry Pi es una de las computadoras de placa única más populares. + +Al igual que un microcontrolador, las computadoras de placa única tienen una CPU, memoria y pines de entrada/salida, pero tienen características adicionales como un chip gráfico para permitirte conectar monitores, salidas de audio y puertos USB para conectar teclados, ratones y otros dispositivos USB estándar como cámaras web o almacenamiento externo. Los programas se almacenan en tarjetas SD o discos duros junto con un sistema operativo, en lugar de un chip de memoria integrado en la placa. + +> 🎓 Puedes pensar en una computadora de placa única como una versión más pequeña y económica de la PC o Mac que estás usando, con la adición de pines GPIO (entrada/salida de propósito general) para interactuar con sensores y actuadores. + +Las computadoras de placa única son computadoras completamente funcionales, por lo que pueden programarse en cualquier lenguaje. Los dispositivos IoT generalmente se programan en Python. + +### Opciones de hardware para el resto de las lecciones + +Todas las lecciones posteriores incluyen tareas que utilizan un dispositivo IoT para interactuar con el mundo físico y comunicarse con la nube. Cada lección admite 3 opciones de dispositivos: Arduino (usando un Seeed Studios Wio Terminal) o una computadora de placa única, ya sea un dispositivo físico (una Raspberry Pi 4) o una computadora de placa única virtual que se ejecuta en tu PC o Mac. + +Puedes leer sobre el hardware necesario para completar todas las tareas en la [guía de hardware](../../../hardware.md). + +> 💁 No necesitas comprar ningún hardware IoT para completar las tareas, puedes hacer todo utilizando una computadora de placa única virtual. + +Qué hardware elijas depende de lo que tengas disponible en casa o en tu escuela, y del lenguaje de programación que conozcas o planees aprender. Ambas variantes de hardware usarán el mismo ecosistema de sensores, por lo que si comienzas con una opción, puedes cambiar a la otra sin tener que reemplazar la mayoría del kit. La computadora de placa única virtual será el equivalente a aprender en una Raspberry Pi, con la mayoría del código transferible a la Pi si eventualmente obtienes un dispositivo y sensores. + +### Kit de desarrollo Arduino + +Si estás interesado en aprender desarrollo de microcontroladores, puedes completar las tareas utilizando un dispositivo Arduino. Necesitarás un conocimiento básico de programación en C/C++, ya que las lecciones solo enseñarán el código relevante para el marco de Arduino, los sensores y actuadores que se utilizan, y las bibliotecas que interactúan con la nube. + +Las tareas utilizarán [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-17441-jabenn) con la [extensión PlatformIO para desarrollo de microcontroladores](https://platformio.org). También puedes usar el IDE de Arduino si tienes experiencia con esta herramienta, ya que no se proporcionarán instrucciones. + +### Kit de desarrollo de computadora de placa única + +Si estás interesado en aprender desarrollo de IoT utilizando computadoras de placa única, puedes completar las tareas utilizando una Raspberry Pi o un dispositivo virtual que se ejecute en tu PC o Mac. + +Necesitarás un conocimiento básico de programación en Python, ya que las lecciones solo enseñarán el código relevante para los sensores y actuadores que se utilizan, y las bibliotecas que interactúan con la nube. + +> 💁 Si quieres aprender a programar en Python, consulta las siguientes dos series de videos: +> +> * [Python para principiantes](https://channel9.msdn.com/Series/Intro-to-Python-Development?WT.mc_id=academic-17441-jabenn) +> * [Más Python para principiantes](https://channel9.msdn.com/Series/More-Python-for-Beginners?WT.mc_id=academic-7372-jabenn) + +Las tareas utilizarán [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-17441-jabenn). + +Si estás utilizando una Raspberry Pi, puedes ejecutar tu Pi utilizando la versión de escritorio completa de Raspberry Pi OS y hacer toda la programación directamente en la Pi utilizando [la versión de VS Code para Raspberry Pi OS](https://code.visualstudio.com/docs/setup/raspberry-pi?WT.mc_id=academic-17441-jabenn), o ejecutar tu Pi como un dispositivo sin cabeza y programar desde tu PC o Mac utilizando VS Code con la [extensión Remote SSH](https://code.visualstudio.com/docs/remote/ssh?WT.mc_id=academic-17441-jabenn), que te permite conectarte a tu Pi y editar, depurar y ejecutar código como si estuvieras programando directamente en ella. + +Si utilizas la opción de dispositivo virtual, programarás directamente en tu computadora. En lugar de acceder a sensores y actuadores, utilizarás una herramienta para simular este hardware, proporcionando valores de sensores que puedes definir y mostrando los resultados de los actuadores en pantalla. + +## Configura tu dispositivo + +Antes de que puedas comenzar a programar tu dispositivo IoT, necesitarás realizar una pequeña configuración. Sigue las instrucciones relevantes a continuación según el dispositivo que vayas a utilizar. +💁 Si aún no tienes un dispositivo, consulta la [guía de hardware](../../../hardware.md) para ayudarte a decidir qué dispositivo vas a usar y qué hardware adicional necesitas comprar. No es necesario que compres hardware, ya que todos los proyectos se pueden ejecutar en hardware virtual. +Estas instrucciones incluyen enlaces a sitios web de terceros de los creadores del hardware o herramientas que estarás utilizando. Esto es para garantizar que siempre tengas las instrucciones más actualizadas para las diversas herramientas y hardware. + +Trabaja en la guía correspondiente para configurar tu dispositivo y completar un proyecto de 'Hola Mundo'. Este será el primer paso para crear una luz nocturna IoT a lo largo de las 4 lecciones de esta parte introductoria. + +* [Arduino - Wio Terminal](wio-terminal.md) +* [Computadora de placa única - Raspberry Pi](pi.md) +* [Computadora de placa única - Dispositivo virtual](virtual-device.md) + +✅ Utilizarás VS Code tanto para Arduino como para computadoras de placa única. Si no lo has usado antes, lee más sobre ello en el [sitio de VS Code](https://code.visualstudio.com?WT.mc_id=academic-17441-jabenn). + +## Aplicaciones del IoT + +El IoT abarca una amplia gama de casos de uso, divididos en algunos grupos principales: + +* IoT para consumidores +* IoT comercial +* IoT industrial +* IoT para infraestructura + +✅ Investiga un poco: Para cada una de las áreas descritas a continuación, encuentra un ejemplo concreto que no esté mencionado en el texto. + +### IoT para consumidores + +El IoT para consumidores se refiere a los dispositivos IoT que los consumidores compran y utilizan en el hogar. Algunos de estos dispositivos son increíblemente útiles, como los altavoces inteligentes, los sistemas de calefacción inteligentes y las aspiradoras robóticas. Otros son cuestionables en su utilidad, como los grifos controlados por voz que luego no puedes apagar porque el control por voz no te escucha debido al sonido del agua corriendo. + +Los dispositivos IoT para consumidores están empoderando a las personas para lograr más en su entorno, especialmente los 1,000 millones que tienen alguna discapacidad. Las aspiradoras robóticas pueden proporcionar pisos limpios a personas con problemas de movilidad que no pueden aspirar por sí mismas, los hornos controlados por voz permiten a personas con visión limitada o problemas de motricidad calentar sus hornos solo con su voz, los monitores de salud permiten a los pacientes controlar condiciones crónicas con actualizaciones más regulares y detalladas sobre su estado. Estos dispositivos se están volviendo tan comunes que incluso los niños pequeños los utilizan como parte de su vida diaria, por ejemplo, estudiantes que hacen educación virtual durante la pandemia de COVID configurando temporizadores en dispositivos inteligentes para seguir su trabajo escolar o alarmas para recordarles reuniones de clase próximas. + +✅ ¿Qué dispositivos IoT para consumidores tienes contigo o en tu hogar? + +### IoT comercial + +El IoT comercial abarca el uso de IoT en el lugar de trabajo. En un entorno de oficina, puede haber sensores de ocupación y detectores de movimiento para gestionar la iluminación y la calefacción, manteniendo las luces y el calor apagados cuando no se necesitan, reduciendo costos y emisiones de carbono. En una fábrica, los dispositivos IoT pueden monitorear peligros de seguridad como trabajadores que no usan cascos o niveles de ruido que han alcanzado niveles peligrosos. En el comercio minorista, los dispositivos IoT pueden medir la temperatura de almacenamiento en frío, alertando al propietario de la tienda si un refrigerador o congelador está fuera del rango de temperatura requerido, o pueden monitorear los artículos en los estantes para dirigir a los empleados a reponer productos que se han vendido. La industria del transporte depende cada vez más del IoT para monitorear la ubicación de los vehículos, rastrear el kilometraje en carretera para el cobro de peajes, verificar el cumplimiento de las horas de conducción y descansos, o notificar al personal cuando un vehículo se acerca a un depósito para prepararse para la carga o descarga. + +✅ ¿Qué dispositivos IoT comerciales tienes en tu escuela o lugar de trabajo? + +### IoT industrial (IIoT) + +El IoT industrial, o IIoT, es el uso de dispositivos IoT para controlar y gestionar maquinaria a gran escala. Esto abarca una amplia gama de casos de uso, desde fábricas hasta agricultura digital. + +Las fábricas utilizan dispositivos IoT de muchas maneras diferentes. La maquinaria puede ser monitoreada con múltiples sensores para rastrear cosas como temperatura, vibración y velocidad de rotación. Estos datos pueden ser monitoreados para permitir que la máquina se detenga si se sale de ciertos límites, por ejemplo, si se calienta demasiado y se apaga. Estos datos también pueden ser recopilados y analizados con el tiempo para realizar mantenimiento predictivo, donde los modelos de IA analizan los datos previos a una falla y los utilizan para predecir otras fallas antes de que ocurran. + +La agricultura digital es importante si el planeta debe alimentar a la población en crecimiento, especialmente para los 2,000 millones de personas en 500 millones de hogares que dependen de la [agricultura de subsistencia](https://wikipedia.org/wiki/Subsistence_agriculture). La agricultura digital puede variar desde sensores de pocos dólares hasta configuraciones comerciales masivas. Un agricultor puede comenzar monitoreando temperaturas y utilizando [días grado de crecimiento](https://wikipedia.org/wiki/Growing_degree-day) para predecir cuándo una cosecha estará lista para la recolección. Pueden conectar el monitoreo de humedad del suelo a sistemas de riego automatizados para dar a sus plantas tanta agua como necesiten, pero no más, asegurando que sus cultivos no se sequen sin desperdiciar agua. Los agricultores incluso están llevando esto más lejos utilizando drones, datos satelitales y IA para monitorear el crecimiento de cultivos, enfermedades y calidad del suelo en grandes áreas de terreno agrícola. + +✅ ¿Qué otros dispositivos IoT podrían ayudar a los agricultores? + +### IoT para infraestructura + +El IoT para infraestructura monitorea y controla la infraestructura local y global que las personas utilizan todos los días. + +[Ciudades inteligentes](https://wikipedia.org/wiki/Smart_city) son áreas urbanas que utilizan dispositivos IoT para recopilar datos sobre la ciudad y usarlos para mejorar cómo funciona. Estas ciudades suelen ser gestionadas con colaboraciones entre gobiernos locales, academia y negocios locales, rastreando y gestionando cosas que varían desde transporte hasta estacionamiento y contaminación. Por ejemplo, en Copenhague, Dinamarca, la contaminación del aire es importante para los residentes locales, por lo que se mide y los datos se utilizan para proporcionar información sobre las rutas más limpias para andar en bicicleta o correr. + +[Redes eléctricas inteligentes](https://wikipedia.org/wiki/Smart_grid) permiten mejores análisis de la demanda de energía al recopilar datos de uso a nivel de hogares individuales. Estos datos pueden guiar decisiones a nivel país, como dónde construir nuevas plantas de energía, y a nivel personal, proporcionando a los usuarios información sobre cuánto energía están utilizando, cuándo la están utilizando e incluso sugerencias para reducir costos, como cargar autos eléctricos por la noche. + +✅ Si pudieras agregar dispositivos IoT para medir algo donde vives, ¿qué sería? + +## Ejemplos de dispositivos IoT que podrías tener cerca de ti + +Te sorprendería saber cuántos dispositivos IoT tienes cerca de ti. Estoy escribiendo esto desde casa y tengo los siguientes dispositivos conectados a Internet con funciones inteligentes como control por aplicación, control por voz o la capacidad de enviarme datos a través de mi teléfono: + +* Múltiples altavoces inteligentes +* Refrigerador, lavavajillas, horno y microondas +* Monitor de electricidad para paneles solares +* Enchufes inteligentes +* Timbre con video y cámaras de seguridad +* Termostato inteligente con múltiples sensores inteligentes de habitación +* Abridor de puerta de garaje +* Sistemas de entretenimiento en el hogar y televisores controlados por voz +* Luces +* Rastreadores de salud y fitness + +Todos estos tipos de dispositivos tienen sensores y/o actuadores y se conectan a Internet. Puedo saber desde mi teléfono si mi puerta de garaje está abierta y pedirle a mi altavoz inteligente que la cierre por mí. Incluso puedo configurarla con un temporizador para que, si sigue abierta por la noche, se cierre automáticamente. Cuando suena mi timbre, puedo ver desde mi teléfono quién está allí, donde sea que esté en el mundo, y hablar con ellos a través de un altavoz y micrófono integrados en el timbre. Puedo monitorear mi glucosa en sangre, ritmo cardíaco y patrones de sueño, buscando patrones en los datos para mejorar mi salud. Puedo controlar mis luces a través de la nube y quedarme en la oscuridad cuando mi conexión a Internet se cae. + +--- + +## 🚀 Desafío + +Haz una lista de tantos dispositivos IoT como puedas que estén en tu hogar, escuela o lugar de trabajo; puede que haya más de los que piensas. + +## Cuestionario posterior a la clase + +[Cuestionario posterior a la clase](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/2) + +## Revisión y autoestudio + +Investiga sobre los beneficios y fracasos de los proyectos de IoT para consumidores. Consulta sitios de noticias para artículos sobre cuando han salido mal, como problemas de privacidad, problemas de hardware o problemas causados por la falta de conectividad. + +Algunos ejemplos: + +* Consulta la cuenta de Twitter **[Internet of Sh*t](https://twitter.com/internetofshit)** *(advertencia de lenguaje)* para algunos buenos ejemplos de fracasos con IoT para consumidores. +* [c|net - Mi Apple Watch salvó mi vida: 5 personas comparten sus historias](https://www.cnet.com/news/apple-watch-lifesaving-health-features-read-5-peoples-stories/) +* [c|net - Técnico de ADT se declara culpable de espiar las cámaras de clientes durante años](https://www.cnet.com/news/adt-home-security-technician-pleads-guilty-to-spying-on-customer-camera-feeds-for-years/) *(advertencia de contenido - voyeurismo no consensuado)* + +## Tarea + +[Investiga un proyecto de IoT](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/1-introduction-to-iot/assignment.md b/translations/es/1-getting-started/lessons/1-introduction-to-iot/assignment.md new file mode 100644 index 00000000..f2381f17 --- /dev/null +++ b/translations/es/1-getting-started/lessons/1-introduction-to-iot/assignment.md @@ -0,0 +1,27 @@ + +# Investigar un proyecto de IoT + +## Instrucciones + +Existen muchos proyectos de IoT a gran y pequeña escala que se están implementando en todo el mundo, desde granjas inteligentes hasta ciudades inteligentes, en monitoreo de salud, transporte y para el uso de espacios públicos. + +Busca en la web detalles de un proyecto que te interese, idealmente uno cercano a donde vives. Explica las ventajas y desventajas del proyecto, como los beneficios que aporta, los problemas que genera y cómo se considera la privacidad. + +## Rúbrica + +| Criterios | Ejemplar | Adecuado | Necesita Mejorar | +| --------- | -------- | -------- | ---------------- | +| Explica las ventajas y desventajas | Dio una explicación clara de las ventajas y desventajas del proyecto | Dio una explicación breve de las ventajas y desventajas | No explicó las ventajas ni las desventajas | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/1-introduction-to-iot/pi.md b/translations/es/1-getting-started/lessons/1-introduction-to-iot/pi.md new file mode 100644 index 00000000..49cf60f3 --- /dev/null +++ b/translations/es/1-getting-started/lessons/1-introduction-to-iot/pi.md @@ -0,0 +1,286 @@ + +# Raspberry Pi + +El [Raspberry Pi](https://raspberrypi.org) es un ordenador de placa única. Puedes añadir sensores y actuadores utilizando una amplia gama de dispositivos y ecosistemas. Para estas lecciones, utilizaremos un ecosistema de hardware llamado [Grove](https://www.seeedstudio.com/category/Grove-c-1003.html). Programarás tu Pi y accederás a los sensores Grove usando Python. + +![Un Raspberry Pi 4](../../../../../translated_images/raspberry-pi-4.fd4590d308c3d456db1327e86b395ddcd735513267aafd4879ea2785f7792eac.es.jpg) + +## Configuración + +Si estás utilizando un Raspberry Pi como tu hardware IoT, tienes dos opciones: puedes trabajar directamente en el Pi y completar todas las lecciones ahí, o puedes conectarte de forma remota a un Pi 'sin cabeza' y programarlo desde tu computadora. + +Antes de comenzar, también necesitas conectar el Grove Base Hat a tu Pi. + +### Tarea - configuración + +Instala el Grove Base Hat en tu Pi y configura el Pi. + +1. Conecta el Grove Base Hat a tu Pi. El conector del hat encaja sobre todos los pines GPIO del Pi, deslizándose completamente hacia abajo para quedar firmemente asentado en la base. Cubre el Pi al colocarse. + + ![Colocando el Grove Hat](../../../../../images/pi-grove-hat-fitting.gif) + +1. Decide cómo quieres programar tu Pi y dirígete a la sección correspondiente a continuación: + + * [Trabajar directamente en tu Pi](../../../../../1-getting-started/lessons/1-introduction-to-iot) + * [Acceso remoto para programar el Pi](../../../../../1-getting-started/lessons/1-introduction-to-iot) + +### Trabajar directamente en tu Pi + +Si deseas trabajar directamente en tu Pi, puedes usar la versión de escritorio del sistema operativo Raspberry Pi OS e instalar todas las herramientas necesarias. + +#### Tarea - trabajar directamente en tu Pi + +Configura tu Pi para el desarrollo. + +1. Sigue las instrucciones en la [guía de configuración de Raspberry Pi](https://projects.raspberrypi.org/en/projects/raspberry-pi-setting-up) para configurar tu Pi, conectarlo a un teclado/ratón/monitor, conectarlo a tu red WiFi o Ethernet, y actualizar el software. + +Para programar el Pi utilizando los sensores y actuadores Grove, necesitarás instalar un editor para escribir el código del dispositivo, así como varias bibliotecas y herramientas que interactúan con el hardware Grove. + +1. Una vez que tu Pi se haya reiniciado, abre el Terminal haciendo clic en el icono **Terminal** en la barra de menú superior, o selecciona *Menú -> Accesorios -> Terminal*. + +1. Ejecuta el siguiente comando para asegurarte de que el sistema operativo y el software instalado estén actualizados: + + ```sh + sudo apt update && sudo apt full-upgrade --yes + ``` + +1. Ejecuta los siguientes comandos para instalar todas las bibliotecas necesarias para el hardware Grove: + + ```sh + sudo apt install git python3-dev python3-pip --yes + + git clone https://github.com/Seeed-Studio/grove.py + cd grove.py + sudo pip3 install . + + sudo raspi-config nonint do_i2c 0 + ``` + + Esto comienza instalando Git, junto con Pip para instalar paquetes de Python. + + Una de las características más potentes de Python es la capacidad de instalar [paquetes Pip](https://pypi.org), que son paquetes de código escritos por otras personas y publicados en Internet. Puedes instalar un paquete Pip en tu computadora con un solo comando y luego usar ese paquete en tu código. + + Los paquetes de Python de Seeed Grove necesitan ser instalados desde el código fuente. Estos comandos clonarán el repositorio que contiene el código fuente de este paquete y luego lo instalarán localmente. + + > 💁 Por defecto, cuando instalas un paquete, está disponible en toda tu computadora, lo que puede generar problemas con las versiones de los paquetes, como cuando una aplicación depende de una versión específica de un paquete que se rompe al instalar una nueva versión para otra aplicación. Para evitar este problema, puedes usar un [entorno virtual de Python](https://docs.python.org/3/library/venv.html), que es esencialmente una copia de Python en una carpeta dedicada. Cuando instalas paquetes Pip, se instalan solo en esa carpeta. Sin embargo, no usarás entornos virtuales al usar tu Pi. El script de instalación de Grove instala los paquetes de Python de Grove de forma global, por lo que, si quisieras usar un entorno virtual, tendrías que configurarlo y luego reinstalar manualmente los paquetes de Grove dentro de ese entorno. Es más fácil usar paquetes globales, especialmente porque muchos desarrolladores de Pi suelen volver a flashear una tarjeta SD limpia para cada proyecto. + + Finalmente, esto habilita la interfaz I2C. + +1. Reinicia el Pi utilizando el menú o ejecutando el siguiente comando en el Terminal: + + ```sh + sudo reboot + ``` + +1. Una vez que el Pi se haya reiniciado, vuelve a abrir el Terminal y ejecuta el siguiente comando para instalar [Visual Studio Code (VS Code)](https://code.visualstudio.com?WT.mc_id=academic-17441-jabenn), que es el editor que usarás para escribir tu código de dispositivo en Python. + + ```sh + sudo apt install code + ``` + + Una vez instalado, VS Code estará disponible desde el menú superior. + + > 💁 Eres libre de usar cualquier IDE o editor de Python para estas lecciones si tienes una herramienta preferida, pero las instrucciones de las lecciones estarán basadas en el uso de VS Code. + +1. Instala Pylance. Esta es una extensión para VS Code que proporciona soporte para el lenguaje Python. Consulta la [documentación de la extensión Pylance](https://marketplace.visualstudio.com/items?WT.mc_id=academic-17441-jabenn&itemName=ms-python.vscode-pylance) para obtener instrucciones sobre cómo instalar esta extensión en VS Code. + +### Acceso remoto para programar el Pi + +En lugar de programar directamente en el Pi, este puede ejecutarse 'sin cabeza', es decir, sin estar conectado a un teclado/ratón/monitor, y configurarse y programarse desde tu computadora utilizando Visual Studio Code. + +#### Configurar el sistema operativo del Pi + +Para programar de forma remota, el sistema operativo del Pi debe instalarse en una tarjeta SD. + +##### Tarea - configurar el sistema operativo del Pi + +Configura el sistema operativo sin cabeza del Pi. + +1. Descarga el **Raspberry Pi Imager** desde la [página de software de Raspberry Pi OS](https://www.raspberrypi.org/software/) e instálalo. + +1. Inserta una tarjeta SD en tu computadora, utilizando un adaptador si es necesario. + +1. Abre el Raspberry Pi Imager. + +1. Desde el Raspberry Pi Imager, selecciona el botón **CHOOSE OS**, luego selecciona *Raspberry Pi OS (Other)*, seguido de *Raspberry Pi OS Lite (32-bit)*. + + ![El Raspberry Pi Imager con Raspberry Pi OS Lite seleccionado](../../../../../translated_images/raspberry-pi-imager.24aedeab9e233d841a1504ed7cfeb871b1f8e1134cfcd8370e7f60a092056be2.es.png) + + > 💁 Raspberry Pi OS Lite es una versión de Raspberry Pi OS que no tiene la interfaz de usuario de escritorio ni herramientas basadas en interfaz gráfica. Estas no son necesarias para un Pi sin cabeza y hacen que la instalación sea más pequeña y el tiempo de arranque más rápido. + +1. Selecciona el botón **CHOOSE STORAGE**, luego selecciona tu tarjeta SD. + +1. Abre las **Opciones Avanzadas** presionando `Ctrl+Shift+X`. Estas opciones permiten preconfigurar el sistema operativo Raspberry Pi antes de grabarlo en la tarjeta SD. + + 1. Marca la casilla **Enable SSH** y establece una contraseña para el usuario `pi`. Esta será la contraseña que usarás para iniciar sesión en el Pi más tarde. + + 1. Si planeas conectarte al Pi por WiFi, marca la casilla **Configure WiFi** e ingresa tu SSID y contraseña de WiFi, además de seleccionar tu país de WiFi. No necesitas hacer esto si usarás un cable Ethernet. Asegúrate de que la red a la que te conectes sea la misma en la que está tu computadora. + + 1. Marca la casilla **Set locale settings** y configura tu país y zona horaria. + + 1. Selecciona el botón **SAVE**. + +1. Selecciona el botón **WRITE** para escribir el sistema operativo en la tarjeta SD. Si estás usando macOS, se te pedirá que ingreses tu contraseña, ya que la herramienta subyacente que escribe imágenes de disco necesita acceso privilegiado. + +El sistema operativo se escribirá en la tarjeta SD y, una vez completado, el sistema operativo expulsará la tarjeta y se te notificará. Retira la tarjeta SD de tu computadora, insértala en el Pi, enciende el Pi y espera unos 2 minutos para que arranque correctamente. + +#### Conectarse al Pi + +El siguiente paso es acceder al Pi de forma remota. Puedes hacerlo utilizando `ssh`, que está disponible en macOS, Linux y versiones recientes de Windows. + +##### Tarea - conectarse al Pi + +Accede al Pi de forma remota. + +1. Abre un Terminal o Símbolo del sistema y escribe el siguiente comando para conectarte al Pi: + + ```sh + ssh pi@raspberrypi.local + ``` + + Si estás en Windows usando una versión más antigua que no tiene `ssh` instalado, puedes usar OpenSSH. Puedes encontrar las instrucciones de instalación en la [documentación de instalación de OpenSSH](https://docs.microsoft.com//windows-server/administration/openssh/openssh_install_firstuse?WT.mc_id=academic-17441-jabenn). + +1. Esto debería conectarte a tu Pi y pedirte la contraseña. + + Poder encontrar computadoras en tu red usando `.local` es una adición relativamente reciente en Linux y Windows. Si estás usando Linux o Windows y obtienes errores sobre que no se encuentra el nombre del host, necesitarás instalar software adicional para habilitar la red ZeroConf (también conocida por Apple como Bonjour): + + 1. Si estás usando Linux, instala Avahi con el siguiente comando: + + ```sh + sudo apt-get install avahi-daemon + ``` + + 1. Si estás usando Windows, la forma más sencilla de habilitar ZeroConf es instalar [Bonjour Print Services for Windows](http://support.apple.com/kb/DL999). También puedes instalar [iTunes para Windows](https://www.apple.com/itunes/download/) para obtener una versión más reciente de la utilidad (que no está disponible de forma independiente). + + > 💁 Si no puedes conectarte usando `raspberrypi.local`, puedes usar la dirección IP de tu Pi. Consulta la [documentación de direcciones IP de Raspberry Pi](https://www.raspberrypi.org/documentation/remote-access/ip-address.md) para obtener instrucciones sobre varias formas de obtener la dirección IP. + +1. Ingresa la contraseña que configuraste en las Opciones Avanzadas del Raspberry Pi Imager. + +#### Configurar software en el Pi + +Una vez conectado al Pi, necesitas asegurarte de que el sistema operativo esté actualizado e instalar varias bibliotecas y herramientas que interactúan con el hardware Grove. + +##### Tarea - configurar software en el Pi + +Configura el software instalado en el Pi e instala las bibliotecas Grove. + +1. Desde tu sesión `ssh`, ejecuta el siguiente comando para actualizar y luego reiniciar el Pi: + + ```sh + sudo apt update && sudo apt full-upgrade --yes && sudo reboot + ``` + + El Pi se actualizará y reiniciará. La sesión `ssh` terminará cuando el Pi se reinicie, así que espera unos 30 segundos y vuelve a conectarte. + +1. Desde la sesión `ssh` reconectada, ejecuta los siguientes comandos para instalar todas las bibliotecas necesarias para el hardware Grove: + + ```sh + sudo apt install git python3-dev python3-pip --yes + + git clone https://github.com/Seeed-Studio/grove.py + cd grove.py + sudo pip3 install . + + sudo raspi-config nonint do_i2c 0 + ``` + + Esto comienza instalando Git, junto con Pip para instalar paquetes de Python. + + Una de las características más potentes de Python es la capacidad de instalar [paquetes Pip](https://pypi.org), que son paquetes de código escritos por otras personas y publicados en Internet. Puedes instalar un paquete Pip en tu computadora con un solo comando y luego usar ese paquete en tu código. + + Los paquetes de Python de Seeed Grove necesitan ser instalados desde el código fuente. Estos comandos clonarán el repositorio que contiene el código fuente de este paquete y luego lo instalarán localmente. + + > 💁 Por defecto, cuando instalas un paquete, está disponible en toda tu computadora, lo que puede generar problemas con las versiones de los paquetes, como cuando una aplicación depende de una versión específica de un paquete que se rompe al instalar una nueva versión para otra aplicación. Para evitar este problema, puedes usar un [entorno virtual de Python](https://docs.python.org/3/library/venv.html), que es esencialmente una copia de Python en una carpeta dedicada. Cuando instalas paquetes Pip, se instalan solo en esa carpeta. Sin embargo, no usarás entornos virtuales al usar tu Pi. El script de instalación de Grove instala los paquetes de Python de Grove de forma global, por lo que, si quisieras usar un entorno virtual, tendrías que configurarlo y luego reinstalar manualmente los paquetes de Grove dentro de ese entorno. Es más fácil usar paquetes globales, especialmente porque muchos desarrolladores de Pi suelen volver a flashear una tarjeta SD limpia para cada proyecto. + + Finalmente, esto habilita la interfaz I2C. + +1. Reinicia el Pi ejecutando el siguiente comando: + + ```sh + sudo reboot + ``` + + La sesión `ssh` terminará cuando el Pi se reinicie. No es necesario volver a conectarse. + +#### Configurar VS Code para acceso remoto + +Una vez que el Pi esté configurado, puedes conectarte a él utilizando Visual Studio Code (VS Code) desde tu computadora. Este es un editor de texto gratuito para desarrolladores que usarás para escribir tu código de dispositivo en Python. + +##### Tarea - configurar VS Code para acceso remoto + +Instala el software necesario y conéctate de forma remota a tu Pi. + +1. Instala VS Code en tu computadora siguiendo la [documentación de VS Code](https://code.visualstudio.com?WT.mc_id=academic-17441-jabenn). + +1. Sigue las instrucciones en la [documentación de desarrollo remoto de VS Code usando SSH](https://code.visualstudio.com/docs/remote/ssh?WT.mc_id=academic-17441-jabenn) para instalar los componentes necesarios. + +1. Siguiendo las mismas instrucciones, conecta VS Code al Pi. + +1. Una vez conectado, sigue las instrucciones de [gestión de extensiones](https://code.visualstudio.com/docs/remote/ssh#_managing-extensions?WT.mc_id=academic-17441-jabenn) para instalar la [extensión Pylance](https://marketplace.visualstudio.com/items?WT.mc_id=academic-17441-jabenn&itemName=ms-python.vscode-pylance) de forma remota en el Pi. + +## Hola mundo +Es tradicional, al comenzar con un nuevo lenguaje de programación o tecnología, crear una aplicación 'Hola Mundo': una pequeña aplicación que muestra algo como el texto `"Hola Mundo"` para confirmar que todas las herramientas están configuradas correctamente. + +La aplicación Hola Mundo para el Pi garantizará que tienes Python y Visual Studio Code instalados correctamente. + +Esta aplicación estará en una carpeta llamada `nightlight`, y se reutilizará con diferentes códigos en partes posteriores de esta tarea para construir la aplicación de luz nocturna. + +### Tarea - hola mundo + +Crea la aplicación Hola Mundo. + +1. Inicia VS Code, ya sea directamente en el Pi, o en tu computadora conectada al Pi usando la extensión Remote SSH. + +1. Abre el Terminal de VS Code seleccionando *Terminal -> Nuevo Terminal*, o presionando `` CTRL+` ``. Se abrirá en el directorio principal del usuario `pi`. + +1. Ejecuta los siguientes comandos para crear un directorio para tu código y un archivo Python llamado `app.py` dentro de ese directorio: + + ```sh + mkdir nightlight + cd nightlight + touch app.py + ``` + +1. Abre esta carpeta en VS Code seleccionando *Archivo -> Abrir...* y seleccionando la carpeta *nightlight*, luego selecciona **OK**. + + ![El cuadro de diálogo de apertura de VS Code mostrando la carpeta nightlight](../../../../../translated_images/vscode-open-nightlight-remote.d3d2a4011e30d535c4b70084f6e94bf6b5b1327fd8e77affe64465ac151ee766.es.png) + +1. Abre el archivo `app.py` desde el explorador de VS Code y agrega el siguiente código: + + ```python + print('Hello World!') + ``` + + La función `print` imprime en la consola lo que se le pase como argumento. + +1. Desde el Terminal de VS Code, ejecuta lo siguiente para correr tu aplicación Python: + + ```sh + python app.py + ``` + + > 💁 Es posible que necesites llamar explícitamente a `python3` para ejecutar este código si tienes Python 2 instalado además de Python 3 (la última versión). Si tienes Python 2 instalado, al llamar a `python` se usará Python 2 en lugar de Python 3. Por defecto, las versiones más recientes del sistema operativo Raspberry Pi solo tienen Python 3 instalado. + + La siguiente salida aparecerá en el terminal: + + ```output + pi@raspberrypi:~/nightlight $ python3 app.py + Hello World! + ``` + +> 💁 Puedes encontrar este código en la carpeta [code/pi](../../../../../1-getting-started/lessons/1-introduction-to-iot/code/pi). + +😀 ¡Tu programa 'Hola Mundo' fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/1-introduction-to-iot/virtual-device.md b/translations/es/1-getting-started/lessons/1-introduction-to-iot/virtual-device.md new file mode 100644 index 00000000..a58ca4d3 --- /dev/null +++ b/translations/es/1-getting-started/lessons/1-introduction-to-iot/virtual-device.md @@ -0,0 +1,245 @@ + +# Computadora de placa única virtual + +En lugar de comprar un dispositivo IoT junto con sensores y actuadores, puedes usar tu computadora para simular hardware IoT. El proyecto [CounterFit](https://github.com/CounterFit-IoT/CounterFit) te permite ejecutar una aplicación localmente que simula hardware IoT como sensores y actuadores, y acceder a ellos desde código Python local escrito de la misma manera que lo harías en una Raspberry Pi utilizando hardware físico. + +## Configuración + +Para usar CounterFit, necesitarás instalar algunos programas gratuitos en tu computadora. + +### Tarea + +Instala el software necesario. + +1. Instala Python. Consulta la [página de descargas de Python](https://www.python.org/downloads/) para obtener instrucciones sobre cómo instalar la última versión de Python. + +1. Instala Visual Studio Code (VS Code). Este es el editor que usarás para escribir el código de tu dispositivo virtual en Python. Consulta la [documentación de VS Code](https://code.visualstudio.com?WT.mc_id=academic-17441-jabenn) para obtener instrucciones sobre cómo instalar VS Code. + + > 💁 Puedes usar cualquier IDE o editor de Python para estas lecciones si tienes una herramienta preferida, pero las instrucciones de las lecciones estarán basadas en el uso de VS Code. + +1. Instala la extensión Pylance de VS Code. Esta es una extensión para VS Code que proporciona soporte para el lenguaje Python. Consulta la [documentación de la extensión Pylance](https://marketplace.visualstudio.com/items?WT.mc_id=academic-17441-jabenn&itemName=ms-python.vscode-pylance) para obtener instrucciones sobre cómo instalar esta extensión en VS Code. + +Las instrucciones para instalar y configurar la aplicación CounterFit se proporcionarán en el momento adecuado en las instrucciones de la asignación, ya que se instala por proyecto. + +## Hola Mundo + +Es tradicional al comenzar con un nuevo lenguaje de programación o tecnología crear una aplicación 'Hola Mundo': una pequeña aplicación que muestra un texto como `"Hello World"` para verificar que todas las herramientas están configuradas correctamente. + +La aplicación Hola Mundo para el hardware IoT virtual asegurará que tienes Python y Visual Studio Code instalados correctamente. También se conectará a CounterFit para los sensores y actuadores IoT virtuales. No usará ningún hardware, solo se conectará para demostrar que todo está funcionando. + +Esta aplicación estará en una carpeta llamada `nightlight`, y se reutilizará con diferentes códigos en partes posteriores de esta asignación para construir la aplicación de luz nocturna. + +### Configurar un entorno virtual de Python + +Una de las características más poderosas de Python es la capacidad de instalar [paquetes Pip](https://pypi.org), que son paquetes de código escritos por otras personas y publicados en Internet. Puedes instalar un paquete Pip en tu computadora con un solo comando y luego usar ese paquete en tu código. Usarás Pip para instalar un paquete que permita interactuar con CounterFit. + +Por defecto, cuando instalas un paquete, está disponible en toda tu computadora, lo que puede generar problemas con las versiones de los paquetes, como que una aplicación dependa de una versión que se rompa al instalar una nueva versión para otra aplicación. Para evitar este problema, puedes usar un [entorno virtual de Python](https://docs.python.org/3/library/venv.html), que es esencialmente una copia de Python en una carpeta dedicada, y cuando instalas paquetes Pip, se instalan solo en esa carpeta. + +> 💁 Si estás usando una Raspberry Pi, no configuraste un entorno virtual en ese dispositivo para gestionar los paquetes Pip; en su lugar, estás usando paquetes globales, ya que los paquetes Grove se instalan globalmente mediante el script de instalación. + +#### Tarea - configurar un entorno virtual de Python + +Configura un entorno virtual de Python e instala los paquetes Pip para CounterFit. + +1. Desde tu terminal o línea de comandos, ejecuta lo siguiente en una ubicación de tu elección para crear y navegar a un nuevo directorio: + + ```sh + mkdir nightlight + cd nightlight + ``` + +1. Ahora ejecuta lo siguiente para crear un entorno virtual en la carpeta `.venv`: + + ```sh + python3 -m venv .venv + ``` + + > 💁 Necesitas llamar explícitamente a `python3` para crear el entorno virtual en caso de que tengas Python 2 instalado además de Python 3 (la última versión). Si tienes Python 2 instalado, llamar a `python` usará Python 2 en lugar de Python 3. + +1. Activa el entorno virtual: + + * En Windows: + * Si estás usando el Command Prompt o el Command Prompt a través de Windows Terminal, ejecuta: + + ```cmd + .venv\Scripts\activate.bat + ``` + + * Si estás usando PowerShell, ejecuta: + + ```powershell + .\.venv\Scripts\Activate.ps1 + ``` + + > Si obtienes un error sobre que los scripts están deshabilitados en este sistema, necesitarás habilitar la ejecución de scripts configurando una política de ejecución adecuada. Puedes hacerlo iniciando PowerShell como administrador y ejecutando el siguiente comando: + + ```powershell + Set-ExecutionPolicy -ExecutionPolicy Unrestricted + ``` + + Ingresa `Y` cuando se te pida confirmar. Luego, reinicia PowerShell e intenta nuevamente. + + Puedes restablecer esta política de ejecución más adelante si es necesario. Puedes leer más sobre esto en la [página de Políticas de Ejecución en Microsoft Docs](https://docs.microsoft.com/powershell/module/microsoft.powershell.core/about/about_execution_policies?WT.mc_id=academic-17441-jabenn). + + * En macOS o Linux, ejecuta: + + ```cmd + source ./.venv/bin/activate + ``` + + > 💁 Estos comandos deben ejecutarse desde la misma ubicación donde ejecutaste el comando para crear el entorno virtual. Nunca necesitarás navegar dentro de la carpeta `.venv`; siempre debes ejecutar el comando de activación y cualquier comando para instalar paquetes o ejecutar código desde la carpeta donde creaste el entorno virtual. + +1. Una vez que el entorno virtual esté activado, el comando `python` por defecto ejecutará la versión de Python que se usó para crear el entorno virtual. Ejecuta lo siguiente para obtener la versión: + + ```sh + python --version + ``` + + La salida debería contener lo siguiente: + + ```output + (.venv) ➜ nightlight python --version + Python 3.9.1 + ``` + + > 💁 Tu versión de Python puede ser diferente; mientras sea la versión 3.6 o superior, estás bien. Si no, elimina esta carpeta, instala una versión más reciente de Python e inténtalo nuevamente. + +1. Ejecuta los siguientes comandos para instalar los paquetes Pip para CounterFit. Estos paquetes incluyen la aplicación principal de CounterFit, así como adaptadores para hardware Grove. Estos adaptadores te permiten escribir código como si estuvieras programando con sensores y actuadores físicos del ecosistema Grove pero conectados a dispositivos IoT virtuales. + + ```sh + pip install CounterFit + pip install counterfit-connection + pip install counterfit-shims-grove + ``` + + Estos paquetes Pip solo se instalarán en el entorno virtual y no estarán disponibles fuera de este. + +### Escribir el código + +Una vez que el entorno virtual de Python esté listo, puedes escribir el código para la aplicación 'Hola Mundo'. + +#### Tarea - escribir el código + +Crea una aplicación en Python para imprimir `"Hello World"` en la consola. + +1. Desde tu terminal o línea de comandos, ejecuta lo siguiente dentro del entorno virtual para crear un archivo Python llamado `app.py`: + + * En Windows, ejecuta: + + ```cmd + type nul > app.py + ``` + + * En macOS o Linux, ejecuta: + + ```cmd + touch app.py + ``` + +1. Abre la carpeta actual en VS Code: + + ```sh + code . + ``` + + > 💁 Si tu terminal devuelve `command not found` en macOS, significa que VS Code no se ha agregado a tu PATH. Puedes agregar VS Code a tu PATH siguiendo las instrucciones en la [sección de Lanzamiento desde la línea de comandos de la documentación de VS Code](https://code.visualstudio.com/docs/setup/mac?WT.mc_id=academic-17441-jabenn#_launching-from-the-command-line) y luego ejecutar el comando nuevamente. VS Code se agrega a tu PATH por defecto en Windows y Linux. + +1. Cuando VS Code se inicie, activará el entorno virtual de Python. El entorno virtual seleccionado aparecerá en la barra de estado inferior: + + ![VS Code mostrando el entorno virtual seleccionado](../../../../../translated_images/vscode-virtual-env.8ba42e04c3d533cf677e16cbe5ed9a3b80f62c6964472dc84b6f940800f0909f.es.png) + +1. Si el terminal de VS Code ya está ejecutándose cuando VS Code se inicia, no tendrá el entorno virtual activado. Lo más fácil es cerrar el terminal usando el botón **Kill the active terminal instance**: + + ![Botón de VS Code para cerrar la instancia activa del terminal](../../../../../translated_images/vscode-kill-terminal.1cc4de7c6f25ee08f423f0ead714e61d069fac1eb2089e97b8a7bbcb3d45fe5e.es.png) + + Puedes saber si el terminal tiene el entorno virtual activado porque el nombre del entorno virtual será un prefijo en el prompt del terminal. Por ejemplo, podría ser: + + ```sh + (.venv) ➜ nightlight + ``` + + Si no tienes `.venv` como prefijo en el prompt, el entorno virtual no está activo en el terminal. + +1. Inicia un nuevo terminal en VS Code seleccionando *Terminal -> New Terminal*, o presionando `` CTRL+` ``. El nuevo terminal cargará el entorno virtual y la llamada para activarlo aparecerá en el terminal. El prompt también tendrá el nombre del entorno virtual (`.venv`): + + ```output + ➜ nightlight source .venv/bin/activate + (.venv) ➜ nightlight + ``` + +1. Abre el archivo `app.py` desde el explorador de VS Code y agrega el siguiente código: + + ```python + print('Hello World!') + ``` + + La función `print` imprime lo que se le pase en la consola. + +1. Desde el terminal de VS Code, ejecuta lo siguiente para ejecutar tu aplicación en Python: + + ```sh + python app.py + ``` + + La salida será la siguiente: + + ```output + (.venv) ➜ nightlight python app.py + Hello World! + ``` + +😀 ¡Tu programa 'Hola Mundo' fue un éxito! + +### Conectar el 'hardware' + +Como un segundo paso de 'Hola Mundo', ejecutarás la aplicación CounterFit y conectarás tu código a ella. Esto es el equivalente virtual de conectar hardware IoT a un kit de desarrollo. + +#### Tarea - conectar el 'hardware' + +1. Desde el terminal de VS Code, inicia la aplicación CounterFit con el siguiente comando: + + ```sh + counterfit + ``` + + La aplicación comenzará a ejecutarse y se abrirá en tu navegador web: + + ![La aplicación CounterFit ejecutándose en un navegador](../../../../../translated_images/counterfit-first-run.433326358b669b31d0e99c3513cb01bfbb13724d162c99cdcc8f51ecf5f9c779.es.png) + + Estará marcada como *Disconnected*, con el LED en la esquina superior derecha apagado. + +1. Agrega el siguiente código al inicio de `app.py`: + + ```python + from counterfit_connection import CounterFitConnection + CounterFitConnection.init('127.0.0.1', 5000) + ``` + + Este código importa la clase `CounterFitConnection` del módulo `counterfit_connection`, que proviene del paquete Pip `counterfit-connection` que instalaste anteriormente. Luego inicializa una conexión a la aplicación CounterFit que se ejecuta en `127.0.0.1`, que es una dirección IP que siempre puedes usar para acceder a tu computadora local (a menudo llamada *localhost*), en el puerto 5000. + + > 💁 Si tienes otras aplicaciones ejecutándose en el puerto 5000, puedes cambiar esto actualizando el puerto en el código y ejecutando CounterFit usando `CounterFit --port `, reemplazando `` con el puerto que deseas usar. + +1. Necesitarás iniciar un nuevo terminal en VS Code seleccionando el botón **Create a new integrated terminal**. Esto se debe a que la aplicación CounterFit está ejecutándose en el terminal actual. + + ![Botón de VS Code para crear un nuevo terminal integrado](../../../../../translated_images/vscode-new-terminal.77db8fc0f9cd31824b0e49a201beafe4ae4616d6c7339992cb2819e789b3eff9.es.png) + +1. En este nuevo terminal, ejecuta el archivo `app.py` como antes. El estado de CounterFit cambiará a **Connected** y el LED se encenderá. + + ![CounterFit mostrando como conectado](../../../../../translated_images/counterfit-connected.ed30b46d8f79b0921f3fc70be10366e596a89dca3f80c2224a9d9fc98fccf884.es.png) + +> 💁 Puedes encontrar este código en la carpeta [code/virtual-device](../../../../../1-getting-started/lessons/1-introduction-to-iot/code/virtual-device). + +😀 ¡Tu conexión al hardware fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/1-introduction-to-iot/wio-terminal.md b/translations/es/1-getting-started/lessons/1-introduction-to-iot/wio-terminal.md new file mode 100644 index 00000000..493e8fa8 --- /dev/null +++ b/translations/es/1-getting-started/lessons/1-introduction-to-iot/wio-terminal.md @@ -0,0 +1,222 @@ + +# Wio Terminal + +El [Wio Terminal de Seeed Studios](https://www.seeedstudio.com/Wio-Terminal-p-4509.html) es un microcontrolador compatible con Arduino, con WiFi y algunos sensores y actuadores integrados, así como puertos para añadir más sensores y actuadores utilizando un ecosistema de hardware llamado [Grove](https://www.seeedstudio.com/category/Grove-c-1003.html). + +![Un Wio Terminal de Seeed Studios](../../../../../translated_images/wio-terminal.b8299ee16587db9aa9e05fabf9721bccd9eb8fb541b7c1a8267241282d81b603.es.png) + +## Configuración + +Para usar tu Wio Terminal, necesitarás instalar software gratuito en tu computadora. También deberás actualizar el firmware del Wio Terminal antes de poder conectarlo a WiFi. + +### Tarea - configuración + +Instala el software necesario y actualiza el firmware. + +1. Instala Visual Studio Code (VS Code). Este será el editor que usarás para escribir el código de tu dispositivo en C/C++. Consulta la [documentación de VS Code](https://code.visualstudio.com?WT.mc_id=academic-17441-jabenn) para obtener instrucciones sobre cómo instalar VS Code. + + > 💁 Otro IDE popular para el desarrollo con Arduino es el [Arduino IDE](https://www.arduino.cc/en/software). Si ya estás familiarizado con esta herramienta, puedes usarla en lugar de VS Code y PlatformIO, pero las lecciones proporcionarán instrucciones basadas en el uso de VS Code. + +1. Instala la extensión PlatformIO para VS Code. Esta es una extensión para VS Code que permite programar microcontroladores en C/C++. Consulta la [documentación de la extensión PlatformIO](https://marketplace.visualstudio.com/items?WT.mc_id=academic-17441-jabenn&itemName=platformio.platformio-ide) para obtener instrucciones sobre cómo instalar esta extensión en VS Code. Esta extensión depende de la extensión Microsoft C/C++ para trabajar con código en C y C++, y esta última se instala automáticamente al instalar PlatformIO. + +1. Conecta tu Wio Terminal a tu computadora. El Wio Terminal tiene un puerto USB-C en la parte inferior, y este debe conectarse a un puerto USB de tu computadora. El Wio Terminal incluye un cable USB-C a USB-A, pero si tu computadora solo tiene puertos USB-C, necesitarás un cable USB-C o un adaptador de USB-A a USB-C. + +1. Sigue las instrucciones en la [documentación de configuración de WiFi del Wio Terminal Wiki](https://wiki.seeedstudio.com/Wio-Terminal-Network-Overview/) para configurar tu Wio Terminal y actualizar el firmware. + +## Hola Mundo + +Es tradicional al comenzar con un nuevo lenguaje de programación o tecnología crear una aplicación 'Hola Mundo': una pequeña aplicación que muestra algo como el texto `"Hello World"` para confirmar que todas las herramientas están configuradas correctamente. + +La aplicación Hola Mundo para el Wio Terminal asegurará que tienes Visual Studio Code instalado correctamente con PlatformIO y configurado para el desarrollo de microcontroladores. + +### Crear un proyecto PlatformIO + +El primer paso es crear un nuevo proyecto usando PlatformIO configurado para el Wio Terminal. + +#### Tarea - crear un proyecto PlatformIO + +Crea el proyecto PlatformIO. + +1. Conecta el Wio Terminal a tu computadora. + +1. Abre VS Code. + +1. El ícono de PlatformIO estará en la barra de menú lateral: + + ![La opción de menú de PlatformIO](../../../../../translated_images/vscode-platformio-menu.297be26b9733e5c4635d9d8e636e93fed2015809eafb7cc8fd409c37b3ef2ef5.es.png) + + Selecciona este ícono, luego selecciona *PIO Home -> Open*. + + ![La opción de abrir PlatformIO](../../../../../translated_images/vscode-platformio-home-open.3f9a41bfd3f4da1c866ec3e69f1675faa30b823b5b58ab58ac88e5df9a85da19.es.png) + +1. Desde la pantalla de bienvenida, selecciona el botón **+ New Project**. + + ![El botón de nuevo proyecto](../../../../../translated_images/vscode-platformio-welcome-new-button.ba6fc8a4c7b78cc822e1ce47ba29c5db96668cce7c5f4adbfd2f1196422baa26.es.png) + +1. Configura el proyecto en el *Asistente de Proyecto*: + + 1. Nombra tu proyecto `nightlight`. + + 1. En el menú desplegable *Board*, escribe `WIO` para filtrar las placas y selecciona *Seeeduino Wio Terminal*. + + 1. Deja el *Framework* como *Arduino*. + + 1. Puedes dejar marcada la casilla *Use default location* o desmarcarla y seleccionar una ubicación para tu proyecto. + + 1. Selecciona el botón **Finish**. + + ![El asistente de proyecto completado](../../../../../translated_images/vscode-platformio-nightlight-project-wizard.5c64db4da6037420827c2597507897233457210ee23975711fa2285efdcd0dc7.es.png) + + PlatformIO descargará los componentes necesarios para compilar el código para el Wio Terminal y creará tu proyecto. Esto puede tardar unos minutos. + +### Explorar el proyecto PlatformIO + +El explorador de VS Code mostrará varios archivos y carpetas creados por el asistente de PlatformIO. + +#### Carpetas + +* `.pio` - esta carpeta contiene datos temporales necesarios para PlatformIO, como bibliotecas o código compilado. Se recrea automáticamente si se elimina, y no necesitas añadirla al control de código fuente si compartes tu proyecto en sitios como GitHub. +* `.vscode` - esta carpeta contiene la configuración utilizada por PlatformIO y VS Code. Se recrea automáticamente si se elimina, y no necesitas añadirla al control de código fuente si compartes tu proyecto en sitios como GitHub. +* `include` - esta carpeta es para archivos de cabecera externos necesarios al añadir bibliotecas adicionales a tu código. No usarás esta carpeta en estas lecciones. +* `lib` - esta carpeta es para bibliotecas externas que quieras llamar desde tu código. No usarás esta carpeta en estas lecciones. +* `src` - esta carpeta contiene el código fuente principal de tu aplicación. Inicialmente, contendrá un único archivo: `main.cpp`. +* `test` - esta carpeta es donde colocarías cualquier prueba unitaria para tu código. + +#### Archivos + +* `main.cpp` - este archivo en la carpeta `src` contiene el punto de entrada para tu aplicación. Ábrelo y contendrá el siguiente código: + + ```cpp + #include + + void setup() { + // put your setup code here, to run once: + } + + void loop() { + // put your main code here, to run repeatedly: + } + ``` + + Cuando el dispositivo se inicia, el framework de Arduino ejecutará la función `setup` una vez, y luego ejecutará la función `loop` repetidamente hasta que el dispositivo se apague. + +* `.gitignore` - este archivo lista los archivos y directorios que deben ignorarse al añadir tu código al control de código fuente, como al subirlo a un repositorio en GitHub. + +* `platformio.ini` - este archivo contiene la configuración para tu dispositivo y aplicación. Ábrelo y contendrá el siguiente código: + + ```ini + [env:seeed_wio_terminal] + platform = atmelsam + board = seeed_wio_terminal + framework = arduino + ``` + + La sección `[env:seeed_wio_terminal]` tiene la configuración para el Wio Terminal. Puedes tener múltiples secciones `env` para que tu código pueda compilarse para varias placas. + + Los otros valores coinciden con la configuración del asistente de proyecto: + + * `platform = atmelsam` define el hardware que usa el Wio Terminal (un microcontrolador basado en ATSAMD51). + * `board = seeed_wio_terminal` define el tipo de placa del microcontrolador (el Wio Terminal). + * `framework = arduino` define que este proyecto usa el framework de Arduino. + +### Escribir la aplicación Hola Mundo + +Ahora estás listo para escribir la aplicación Hola Mundo. + +#### Tarea - escribir la aplicación Hola Mundo + +Escribe la aplicación Hola Mundo. + +1. Abre el archivo `main.cpp` en VS Code. + +1. Cambia el código para que coincida con lo siguiente: + + ```cpp + #include + + void setup() + { + Serial.begin(9600); + + while (!Serial) + ; // Wait for Serial to be ready + + delay(1000); + } + + void loop() + { + Serial.println("Hello World"); + delay(5000); + } + ``` + + La función `setup` inicializa una conexión al puerto serie, en este caso, el puerto USB que se usa para conectar el Wio Terminal a tu computadora. El parámetro `9600` es la [tasa de baudios](https://wikipedia.org/wiki/Symbol_rate) (también conocida como tasa de símbolos), o la velocidad a la que se enviarán los datos por el puerto serie en bits por segundo. Esta configuración significa que se envían 9,600 bits (0s y 1s) de datos por segundo. Luego, espera a que el puerto serie esté listo. + + La función `loop` envía la línea `Hello World!` al puerto serie, junto con un carácter de nueva línea. Luego, duerme durante 5,000 milisegundos o 5 segundos. Después de que termina el `loop`, se ejecuta nuevamente, y así sucesivamente mientras el microcontrolador esté encendido. + +1. Pon tu Wio Terminal en modo de carga. Necesitarás hacer esto cada vez que subas un nuevo código al dispositivo: + + 1. Baja dos veces rápidamente el interruptor de encendido; este volverá automáticamente a la posición de encendido cada vez. + + 1. Verifica el LED azul de estado a la derecha del puerto USB. Debería estar pulsando. + + [![Un video que muestra cómo poner el Wio Terminal en modo de carga](https://img.youtube.com/vi/LeKU_7zLRrQ/0.jpg)](https://youtu.be/LeKU_7zLRrQ) + + Haz clic en la imagen de arriba para ver un video que muestra cómo hacerlo. + +1. Compila y sube el código al Wio Terminal. + + 1. Abre el paleta de comandos de VS Code. + + 1. Escribe `PlatformIO Upload` para buscar la opción de carga y selecciona *PlatformIO: Upload*. + + ![La opción de carga de PlatformIO en la paleta de comandos](../../../../../translated_images/vscode-platformio-upload-command-palette.9e0f49cf80d1f1c3eb5c6689b8705ad8b89f0374b21698e996fec11e4ed09347.es.png) + + PlatformIO compilará automáticamente el código si es necesario antes de subirlo. + + 1. El código será compilado y subido al Wio Terminal. + + > 💁 Si estás usando macOS, aparecerá una notificación sobre un *DISCO NO EXPULSADO CORRECTAMENTE*. Esto ocurre porque el Wio Terminal se monta como una unidad durante el proceso de carga y se desconecta cuando el código compilado se escribe en el dispositivo. Puedes ignorar esta notificación. + + ⚠️ Si obtienes errores sobre que el puerto de carga no está disponible, primero asegúrate de que el Wio Terminal esté conectado a tu computadora, encendido con el interruptor en el lado izquierdo de la pantalla y en modo de carga. La luz verde en la parte inferior debería estar encendida y la luz azul debería estar pulsando. Si aún obtienes el error, baja el interruptor de encendido/apagado dos veces rápidamente nuevamente para forzar al Wio Terminal a entrar en modo de carga e intenta subir el código nuevamente. + +PlatformIO tiene un Monitor Serie que puede monitorear los datos enviados por el cable USB desde el Wio Terminal. Esto te permite monitorear los datos enviados por el comando `Serial.println("Hello World");`. + +1. Abre el paleta de comandos de VS Code. + +1. Escribe `PlatformIO Serial` para buscar la opción del Monitor Serie y selecciona *PlatformIO: Serial Monitor*. + + ![La opción del Monitor Serie de PlatformIO en la paleta de comandos](../../../../../translated_images/vscode-platformio-serial-monitor-command-palette.b348ec841b8a1c14af503d6fc0bf73c657c79c9acc12a6b6dd485ce3b5826f48.es.png) + + Se abrirá un nuevo terminal y los datos enviados por el puerto serie se transmitirán a este terminal: + + ```output + > Executing task: platformio device monitor < + + --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time + --- More details at http://bit.ly/pio-monitor-filters + --- Miniterm on /dev/cu.usbmodem101 9600,8,N,1 --- + --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + Hello World + Hello World + ``` + + `Hello World` se imprimirá en el monitor serie cada 5 segundos. + +> 💁 Puedes encontrar este código en la carpeta [code/wio-terminal](../../../../../1-getting-started/lessons/1-introduction-to-iot/code/wio-terminal). + +😀 ¡Tu programa 'Hola Mundo' fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/2-deeper-dive/README.md b/translations/es/1-getting-started/lessons/2-deeper-dive/README.md new file mode 100644 index 00000000..d459db23 --- /dev/null +++ b/translations/es/1-getting-started/lessons/2-deeper-dive/README.md @@ -0,0 +1,277 @@ + +# Una exploración más profunda en IoT + +![Un resumen visual de esta lección](../../../../../translated_images/lesson-2.324b0580d620c25e0a24fb7fddfc0b29a846dd4b82c08e7a9466d580ee78ce51.es.jpg) + +> Resumen visual por [Nitya Narasimhan](https://github.com/nitya). Haz clic en la imagen para verla en mayor tamaño. + +Esta lección fue impartida como parte de la [serie Hello IoT](https://youtube.com/playlist?list=PLmsFUfdnGr3xRts0TIwyaHyQuHaNQcb6-) del [Microsoft Reactor](https://developer.microsoft.com/reactor/?WT.mc_id=academic-17441-jabenn). La lección se presentó en 2 videos: una clase de 1 hora y una sesión de preguntas y respuestas de 1 hora para profundizar en los temas y responder dudas. + +[![Lección 2: Una exploración más profunda en IoT](https://img.youtube.com/vi/t0SySWw3z9M/0.jpg)](https://youtu.be/t0SySWw3z9M) + +[![Lección 2: Una exploración más profunda en IoT - Horas de oficina](https://img.youtube.com/vi/tTZYf9EST1E/0.jpg)](https://youtu.be/tTZYf9EST1E) + +> 🎥 Haz clic en las imágenes de arriba para ver los videos + +## Cuestionario previo a la lección + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/3) + +## Introducción + +En esta lección profundizaremos en algunos de los conceptos cubiertos en la lección anterior. + +En esta lección veremos: + +* [Componentes de una aplicación IoT](../../../../../1-getting-started/lessons/2-deeper-dive) +* [Exploración más profunda en microcontroladores](../../../../../1-getting-started/lessons/2-deeper-dive) +* [Exploración más profunda en computadoras de placa única](../../../../../1-getting-started/lessons/2-deeper-dive) + +## Componentes de una aplicación IoT + +Los dos componentes principales de una aplicación IoT son el *Internet* y el *dispositivo*. Veamos estos dos componentes con más detalle. + +### El Dispositivo + +![Una Raspberry Pi 4](../../../../../translated_images/raspberry-pi-4.fd4590d308c3d456db1327e86b395ddcd735513267aafd4879ea2785f7792eac.es.jpg) + +La parte del **Dispositivo** en IoT se refiere a un aparato que puede interactuar con el mundo físico. Estos dispositivos suelen ser computadoras pequeñas y de bajo costo, que funcionan a bajas velocidades y consumen poca energía. Por ejemplo, microcontroladores simples con kilobytes de RAM (en lugar de gigabytes como en una PC) que operan a solo unos cientos de megahercios (en lugar de gigahercios como en una PC), pero que a veces consumen tan poca energía que pueden funcionar durante semanas, meses o incluso años con baterías. + +Estos dispositivos interactúan con el mundo físico, ya sea utilizando sensores para recopilar datos de su entorno o controlando salidas o actuadores para realizar cambios físicos. Un ejemplo típico es un termostato inteligente: un dispositivo que tiene un sensor de temperatura, un medio para establecer una temperatura deseada como un dial o pantalla táctil, y una conexión a un sistema de calefacción o enfriamiento que puede encenderse cuando la temperatura detectada está fuera del rango deseado. El sensor de temperatura detecta que la habitación está demasiado fría y un actuador enciende la calefacción. + +![Un diagrama que muestra la temperatura y un dial como entradas a un dispositivo IoT, y el control de un calentador como salida](../../../../../translated_images/basic-thermostat.a923217fd1f37e5a6f3390396a65c22a387419ea2dd17e518ec24315ba6ae9a8.es.png) + +Existen una gran variedad de dispositivos que pueden actuar como dispositivos IoT, desde hardware dedicado que detecta una sola cosa, hasta dispositivos de propósito general, ¡incluso tu smartphone! Un smartphone puede usar sensores para detectar el mundo que lo rodea y actuadores para interactuar con él, por ejemplo, utilizando un sensor GPS para detectar tu ubicación y un altavoz para darte instrucciones de navegación hacia un destino. + +✅ Piensa en otros sistemas que tengas a tu alrededor que lean datos de un sensor y los utilicen para tomar decisiones. Un ejemplo sería el termostato de un horno. ¿Puedes encontrar más? + +### El Internet + +La parte del **Internet** en una aplicación IoT consiste en aplicaciones a las que el dispositivo IoT puede conectarse para enviar y recibir datos, así como otras aplicaciones que pueden procesar los datos del dispositivo IoT y ayudar a tomar decisiones sobre qué solicitudes enviar a los actuadores del dispositivo IoT. + +Una configuración típica sería tener algún tipo de servicio en la nube al que el dispositivo IoT se conecte, y este servicio en la nube maneja cosas como la seguridad, además de recibir mensajes del dispositivo IoT y enviar mensajes de vuelta al dispositivo. Este servicio en la nube luego se conecta a otras aplicaciones que pueden procesar o almacenar datos de sensores, o usar los datos de sensores junto con datos de otros sistemas para tomar decisiones. + +Los dispositivos no siempre se conectan directamente a Internet a través de WiFi o conexiones cableadas. Algunos dispositivos usan redes en malla para comunicarse entre sí mediante tecnologías como Bluetooth, conectándose a través de un dispositivo central que tiene conexión a Internet. + +En el ejemplo de un termostato inteligente, el termostato se conectaría usando WiFi doméstico a un servicio en la nube. Enviaría los datos de temperatura a este servicio en la nube, y desde allí se escribirían en una base de datos que permitiría al propietario verificar las temperaturas actuales y pasadas usando una aplicación en su teléfono. Otro servicio en la nube sabría qué temperatura desea el propietario y enviaría mensajes de vuelta al dispositivo IoT a través del servicio en la nube para indicarle al sistema de calefacción que se encienda o apague. + +![Un diagrama que muestra la temperatura y un dial como entradas a un dispositivo IoT, el dispositivo IoT con comunicación bidireccional con la nube, que a su vez tiene comunicación bidireccional con un teléfono, y el control de un calentador como salida del dispositivo IoT](../../../../../translated_images/mobile-controlled-thermostat.4a994010473d8d6a52ba68c67e5f02dc8928c717e93ca4b9bc55525aa75bbb60.es.png) + +Una versión aún más inteligente podría usar IA en la nube con datos de otros sensores conectados a otros dispositivos IoT, como sensores de ocupación que detectan qué habitaciones están en uso, así como datos como el clima e incluso tu calendario, para tomar decisiones sobre cómo ajustar la temperatura de manera inteligente. Por ejemplo, podría apagar la calefacción si detecta en tu calendario que estás de vacaciones, o apagar la calefacción habitación por habitación dependiendo de cuáles usas, aprendiendo de los datos para ser cada vez más preciso con el tiempo. + +![Un diagrama que muestra múltiples sensores de temperatura y un dial como entradas a un dispositivo IoT, el dispositivo IoT con comunicación bidireccional con la nube, que a su vez tiene comunicación bidireccional con un teléfono, un calendario y un servicio meteorológico, y el control de un calentador como salida del dispositivo IoT](../../../../../translated_images/smarter-thermostat.a75855f15d2d9e63d5da9d7ba5847a987f6c9d98e96e770c203532275194e27d.es.png) + +✅ ¿Qué otros datos podrían ayudar a hacer un termostato conectado a Internet más inteligente? + +### IoT en el Borde + +Aunque la "I" en IoT significa Internet, estos dispositivos no siempre tienen que conectarse a Internet. En algunos casos, los dispositivos pueden conectarse a dispositivos de "borde" (edge) - dispositivos de puerta de enlace que funcionan en tu red local, lo que permite procesar datos sin necesidad de hacer una llamada a través de Internet. Esto puede ser más rápido cuando tienes una gran cantidad de datos o una conexión a Internet lenta, permite operar sin conexión donde la conectividad a Internet no es posible, como en un barco o en una zona de desastre al responder a una crisis humanitaria, y permite mantener los datos privados. Algunos dispositivos contienen código de procesamiento creado con herramientas en la nube y lo ejecutan localmente para recopilar y responder a datos sin usar una conexión a Internet para tomar decisiones. + +Un ejemplo de esto es un dispositivo inteligente para el hogar como un Apple HomePod, Amazon Alexa o Google Home, que escucha tu voz utilizando modelos de IA entrenados en la nube, pero que se ejecutan localmente en el dispositivo. Estos dispositivos "despiertan" cuando se pronuncia una palabra o frase específica, y solo entonces envían tu voz a través de Internet para su procesamiento. El dispositivo deja de enviar datos de voz en un momento apropiado, como cuando detecta una pausa en tu discurso. Todo lo que dices antes de despertar al dispositivo con la palabra clave, y todo lo que dices después de que el dispositivo ha dejado de escuchar, no se envía a través de Internet al proveedor del dispositivo, y por lo tanto permanece privado. + +✅ Piensa en otros escenarios donde la privacidad sea importante, de modo que el procesamiento de datos sería mejor realizarlo en el borde en lugar de en la nube. Como pista: piensa en dispositivos IoT con cámaras u otros dispositivos de imagen. + +### Seguridad en IoT + +Con cualquier conexión a Internet, la seguridad es una consideración importante. Existe un viejo chiste que dice que "la S en IoT significa Seguridad" - no hay una "S" en IoT, lo que implica que no es seguro. + +Los dispositivos IoT se conectan a un servicio en la nube, y por lo tanto son tan seguros como ese servicio en la nube. Si tu servicio en la nube permite que cualquier dispositivo se conecte, entonces se pueden enviar datos maliciosos o pueden ocurrir ataques de virus. Esto puede tener consecuencias muy reales, ya que los dispositivos IoT interactúan y controlan otros dispositivos. Por ejemplo, el [gusano Stuxnet](https://wikipedia.org/wiki/Stuxnet) manipuló válvulas en centrifugadoras para dañarlas. Los hackers también han aprovechado [la mala seguridad para acceder a monitores de bebés](https://www.npr.org/sections/thetwo-way/2018/06/05/617196788/s-c-mom-says-baby-monitor-was-hacked-experts-say-many-devices-are-vulnerable) y otros dispositivos de vigilancia en el hogar. + +> 💁 A veces, los dispositivos IoT y los dispositivos de borde funcionan en una red completamente aislada de Internet para mantener los datos privados y seguros. Esto se conoce como [air-gapping](https://wikipedia.org/wiki/Air_gap_(networking)). + +## Exploración más profunda en microcontroladores + +En la lección anterior, presentamos los microcontroladores. Ahora profundicemos en ellos. + +### CPU + +La CPU es el "cerebro" del microcontrolador. Es el procesador que ejecuta tu código y puede enviar y recibir datos de cualquier dispositivo conectado. Las CPUs pueden contener uno o más núcleos, que son esencialmente varias CPUs que pueden trabajar juntas para ejecutar tu código. + +Las CPUs dependen de un reloj que marca millones o miles de millones de veces por segundo. Cada marca, o ciclo, sincroniza las acciones que la CPU puede realizar. Con cada marca, la CPU puede ejecutar una instrucción de un programa, como recuperar datos de un dispositivo externo o realizar un cálculo matemático. Este ciclo regular permite que todas las acciones se completen antes de que se procese la siguiente instrucción. + +Cuanto más rápido sea el ciclo del reloj, más instrucciones se pueden procesar por segundo, y por lo tanto, más rápida será la CPU. Las velocidades de las CPUs se miden en [Hertz (Hz)](https://wikipedia.org/wiki/Hertz), una unidad estándar donde 1 Hz significa un ciclo o marca del reloj por segundo. + +> 🎓 Las velocidades de las CPUs a menudo se dan en MHz o GHz. 1MHz es 1 millón de Hz, 1GHz es 1 mil millones de Hz. + +> 💁 Las CPUs ejecutan programas utilizando el [ciclo de búsqueda-decodificación-ejecución](https://wikipedia.org/wiki/Instruction_cycle). Por cada marca del reloj, la CPU buscará la siguiente instrucción en la memoria, la decodificará y luego la ejecutará, como usar una unidad lógica aritmética (ALU) para sumar 2 números. Algunas ejecuciones tomarán varios ciclos para completarse, por lo que el siguiente ciclo se ejecutará en la siguiente marca después de que la instrucción haya terminado. + +![El ciclo de búsqueda-decodificación-ejecución mostrando la búsqueda de una instrucción del programa almacenado en RAM, luego decodificándola y ejecutándola en una CPU](../../../../../translated_images/fetch-decode-execute.2fd6f150f6280392807f4475382319abd0cee0b90058e1735444d6baa6f2078c.es.png) + +Los microcontroladores tienen velocidades de reloj mucho más bajas que las computadoras de escritorio o portátiles, o incluso la mayoría de los smartphones. Por ejemplo, el Wio Terminal tiene una CPU que funciona a 120MHz o 120,000,000 ciclos por segundo. + +✅ Una PC o Mac promedio tiene una CPU con múltiples núcleos que funcionan a varios gigahercios, lo que significa que el reloj marca miles de millones de veces por segundo. Investiga la velocidad del reloj de tu computadora y compara cuántas veces es más rápida que el Wio Terminal. + +Cada ciclo del reloj consume energía y genera calor. Cuanto más rápidas sean las marcas, más energía se consume y más calor se genera. Las PCs tienen disipadores de calor y ventiladores para eliminar el calor, sin los cuales se sobrecalentarían y se apagarían en segundos. Los microcontroladores a menudo no tienen ninguno de estos, ya que funcionan mucho más fríos y, por lo tanto, mucho más lentos. Las PCs funcionan con energía de red o baterías grandes durante unas pocas horas, mientras que los microcontroladores pueden funcionar durante días, meses o incluso años con baterías pequeñas. Los microcontroladores también pueden tener núcleos que funcionan a diferentes velocidades, cambiando a núcleos más lentos y de bajo consumo cuando la demanda en la CPU es baja para reducir el consumo de energía. + +> 💁 Algunas PCs y Macs están adoptando la misma combinación de núcleos rápidos de alto rendimiento y núcleos más lentos de bajo consumo, cambiando entre ellos para ahorrar batería. Por ejemplo, el chip M1 en las últimas laptops de Apple puede alternar entre 4 núcleos de rendimiento y 4 núcleos de eficiencia para optimizar la duración de la batería o la velocidad dependiendo de la tarea que se esté ejecutando. + +✅ Investiga un poco: Lee sobre las CPUs en el [artículo de Wikipedia sobre CPUs](https://wikipedia.org/wiki/Central_processing_unit) + +#### Tarea + +Investiga el Wio Terminal. + +Si estás utilizando un Wio Terminal para estas lecciones, intenta encontrar la CPU. Busca la sección *Hardware Overview* en la [página del producto Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html) para ver una imagen de los componentes internos, e intenta localizar la CPU a través de la ventana de plástico transparente en la parte trasera. + +### Memoria + +Los microcontroladores suelen tener dos tipos de memoria: memoria de programa y memoria de acceso aleatorio (RAM). + +La memoria de programa es no volátil, lo que significa que lo que se escribe en ella permanece incluso cuando no hay energía en el dispositivo. Esta es la memoria que almacena el código de tu programa. + +La RAM es la memoria utilizada por el programa para ejecutarse, conteniendo variables asignadas por tu programa y datos recopilados de periféricos. La RAM es volátil, lo que significa que cuando se corta la energía, su contenido se pierde, lo que efectivamente reinicia tu programa. +> 🎓 La memoria del programa almacena tu código y permanece incluso cuando no hay energía. +> 🎓 La RAM se utiliza para ejecutar tu programa y se reinicia cuando no hay energía + +Al igual que con la CPU, la memoria en un microcontrolador es órdenes de magnitud más pequeña que en un PC o Mac. Un PC típico podría tener 8 Gigabytes (GB) de RAM, o 8,000,000,000 bytes, con cada byte teniendo suficiente espacio para almacenar una sola letra o un número del 0 al 255. Un microcontrolador tendría solo Kilobytes (KB) de RAM, siendo un kilobyte 1,000 bytes. El Wio Terminal mencionado anteriormente tiene 192KB de RAM, o 192,000 bytes, ¡más de 40,000 veces menos que un PC promedio! + +El diagrama a continuación muestra la diferencia relativa de tamaño entre 192KB y 8GB: el pequeño punto en el centro representa 192KB. + +![Una comparación entre 192KB y 8GB - más de 40,000 veces más grande](../../../../../translated_images/ram-comparison.6beb73541b42ac6ffde64cdf79fc925a84b932ce7ebd4d41d5fd7afc1257a696.es.png) + +El almacenamiento de programas también es más pequeño que en un PC. Un PC típico podría tener un disco duro de 500GB para almacenamiento de programas, mientras que un microcontrolador podría tener solo kilobytes o tal vez unos pocos megabytes (MB) de almacenamiento (1MB son 1,000KB, o 1,000,000 bytes). El Wio Terminal tiene 4MB de almacenamiento para programas. + +✅ Investiga un poco: ¿Cuánta RAM y almacenamiento tiene la computadora que estás usando para leer esto? ¿Cómo se compara con un microcontrolador? + +### Entrada/Salida + +Los microcontroladores necesitan conexiones de entrada y salida (I/O) para leer datos de sensores y enviar señales de control a actuadores. Generalmente contienen varios pines de entrada/salida de propósito general (GPIO). Estos pines pueden configurarse en el software como entrada (es decir, reciben una señal) o salida (envían una señal). + +🧠⬅️ Los pines de entrada se utilizan para leer valores de sensores. + +🧠➡️ Los pines de salida envían instrucciones a actuadores. + +✅ Aprenderás más sobre esto en una lección posterior. + +#### Tarea + +Investiga el Wio Terminal. + +Si estás utilizando un Wio Terminal para estas lecciones, encuentra los pines GPIO. Busca la sección *Pinout diagram* en la [página del producto Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html) para aprender qué pines son cuáles. El Wio Terminal viene con una pegatina que puedes montar en la parte trasera con los números de los pines, así que colócala ahora si no lo has hecho. + +### Tamaño físico + +Los microcontroladores suelen ser pequeños en tamaño, siendo el más pequeño, un [Freescale Kinetis KL03 MCU lo suficientemente pequeño como para caber en el hoyuelo de una pelota de golf](https://www.edn.com/tiny-arm-cortex-m0-based-mcu-shrinks-package/). Solo la CPU en un PC puede medir 40mm x 40mm, y eso sin incluir los disipadores de calor y ventiladores necesarios para garantizar que la CPU pueda funcionar más de unos segundos sin sobrecalentarse, siendo sustancialmente más grande que un microcontrolador completo. El kit de desarrollo Wio Terminal con un microcontrolador, carcasa, pantalla y una gama de conexiones y componentes no es mucho más grande que una CPU Intel i9 desnuda, y sustancialmente más pequeño que la CPU con un disipador de calor y ventilador. + +| Dispositivo | Tamaño | +| -------------------------------- | --------------------- | +| Freescale Kinetis KL03 | 1.6mm x 2mm x 1mm | +| Wio Terminal | 72mm x 57mm x 12mm | +| Intel i9 CPU, disipador y ventilador | 136mm x 145mm x 103mm | + +### Frameworks y sistemas operativos + +Debido a su baja velocidad y tamaño de memoria, los microcontroladores no ejecutan un sistema operativo (OS) en el sentido de escritorio de la palabra. El sistema operativo que hace que tu computadora funcione (Windows, Linux o macOS) necesita mucha memoria y potencia de procesamiento para ejecutar tareas que son completamente innecesarias para un microcontrolador. Recuerda que los microcontroladores suelen programarse para realizar una o más tareas muy específicas, a diferencia de una computadora de propósito general como un PC o Mac que necesita soportar una interfaz de usuario, reproducir música o películas, proporcionar herramientas para escribir documentos o código, jugar o navegar por Internet. + +Para programar un microcontrolador sin un OS necesitas algunas herramientas que te permitan construir tu código de una manera que el microcontrolador pueda ejecutar, utilizando APIs que puedan comunicarse con cualquier periférico. Cada microcontrolador es diferente, por lo que los fabricantes normalmente soportan frameworks estándar que te permiten seguir una 'receta' estándar para construir tu código y ejecutarlo en cualquier microcontrolador que soporte ese framework. + +Puedes programar microcontroladores utilizando un OS, a menudo referido como un sistema operativo en tiempo real (RTOS), ya que están diseñados para manejar el envío de datos hacia y desde periféricos en tiempo real. Estos sistemas operativos son muy ligeros y proporcionan características como: + +* Multitarea, permitiendo que tu código ejecute más de un bloque de código al mismo tiempo, ya sea en múltiples núcleos o turnándose en un núcleo. +* Redes para permitir la comunicación segura a través de Internet. +* Componentes de interfaz gráfica de usuario (GUI) para construir interfaces de usuario (UI) en dispositivos que tienen pantallas. + +✅ Investiga algunos RTOS diferentes: [Azure RTOS](https://azure.microsoft.com/services/rtos/?WT.mc_id=academic-17441-jabenn), [FreeRTOS](https://www.freertos.org), [Zephyr](https://www.zephyrproject.org) + +#### Arduino + +![El logo de Arduino](../../../../../images/arduino-logo.svg) + +[Arduino](https://www.arduino.cc) es probablemente el framework de microcontroladores más popular, especialmente entre estudiantes, aficionados y creadores. Arduino es una plataforma de electrónica de código abierto que combina software y hardware. Puedes comprar placas compatibles con Arduino de Arduino mismo o de otros fabricantes, y luego programarlas utilizando el framework Arduino. + +Las placas Arduino se programan en C o C++. Usar C/C++ permite que tu código se compile de manera muy compacta y se ejecute rápidamente, algo necesario en un dispositivo con recursos limitados como un microcontrolador. El núcleo de una aplicación Arduino se conoce como un sketch y es código C/C++ con 2 funciones: `setup` y `loop`. Cuando la placa se inicia, el código del framework Arduino ejecutará la función `setup` una vez, y luego ejecutará la función `loop` una y otra vez, ejecutándola continuamente hasta que se apague la energía. + +Escribirías tu código de configuración en la función `setup`, como conectarte a WiFi y servicios en la nube o inicializar pines para entrada y salida. Tu código de bucle estaría en la función `loop`, como leer de un sensor y enviar el valor a la nube. Normalmente incluirías un retraso en cada bucle, por ejemplo, si solo quieres que los datos del sensor se envíen cada 10 segundos, agregarías un retraso de 10 segundos al final del bucle para que el microcontrolador pueda dormir, ahorrando energía, y luego ejecutar el bucle nuevamente cuando sea necesario 10 segundos después. + +![Un sketch de Arduino ejecutando setup primero, luego ejecutando loop repetidamente](../../../../../translated_images/arduino-sketch.79590cb837ff7a7c6a68d1afda6cab83fd53d3bb1bd9a8bf2eaf8d693a4d3ea6.es.png) + +✅ Esta arquitectura de programa se conoce como un *bucle de eventos* o *bucle de mensajes*. Muchas aplicaciones utilizan esto en segundo plano y es el estándar para la mayoría de las aplicaciones de escritorio que se ejecutan en sistemas operativos como Windows, macOS o Linux. El `loop` escucha mensajes de componentes de la interfaz de usuario como botones o dispositivos como el teclado, y responde a ellos. Puedes leer más en este [artículo sobre el bucle de eventos](https://wikipedia.org/wiki/Event_loop). + +Arduino proporciona bibliotecas estándar para interactuar con microcontroladores y los pines de I/O, con diferentes implementaciones internas para ejecutarse en diferentes microcontroladores. Por ejemplo, la función [`delay`](https://www.arduino.cc/reference/en/language/functions/time/delay/) pausará el programa durante un período de tiempo dado, la función [`digitalRead`](https://www.arduino.cc/reference/en/language/functions/digital-io/digitalread/) leerá un valor de `HIGH` o `LOW` del pin dado, independientemente de en qué placa se ejecute el código. Estas bibliotecas estándar significan que el código Arduino escrito para una placa puede recompilarse para cualquier otra placa Arduino y funcionará, suponiendo que los pines sean los mismos y las placas soporten las mismas características. + +Existe un gran ecosistema de bibliotecas de terceros para Arduino que te permiten agregar características adicionales a tus proyectos Arduino, como usar sensores y actuadores o conectarte a servicios IoT en la nube. + +##### Tarea + +Investiga el Wio Terminal. + +Si estás utilizando un Wio Terminal para estas lecciones, vuelve a leer el código que escribiste en la última lección. Encuentra las funciones `setup` y `loop`. Monitorea la salida serial para ver cómo se llama repetidamente a la función `loop`. Intenta agregar código a la función `setup` para escribir en el puerto serial y observa que este código solo se llama una vez cada vez que reinicias. Intenta reiniciar tu dispositivo con el interruptor de encendido en el lateral para mostrar que esto se llama cada vez que el dispositivo se reinicia. + +## Exploración más profunda de las computadoras de placa única + +En la última lección, introdujimos las computadoras de placa única. Ahora profundicemos en ellas. + +### Raspberry Pi + +![El logo de Raspberry Pi](../../../../../translated_images/raspberry-pi-logo.4efaa16605cee05489d8fa53941e991b3757aa24c20a95abdcf8cfd761953596.es.png) + +La [Fundación Raspberry Pi](https://www.raspberrypi.org) es una organización benéfica del Reino Unido fundada en 2009 para promover el estudio de la informática, especialmente a nivel escolar. Como parte de esta misión, desarrollaron una computadora de placa única, llamada Raspberry Pi. Actualmente, las Raspberry Pi están disponibles en 3 variantes: una versión de tamaño completo, la más pequeña Pi Zero, y un módulo de computación que puede integrarse en tu dispositivo IoT final. + +![Un Raspberry Pi 4](../../../../../translated_images/raspberry-pi-4.fd4590d308c3d456db1327e86b395ddcd735513267aafd4879ea2785f7792eac.es.jpg) + +La última iteración de la Raspberry Pi de tamaño completo es la Raspberry Pi 4B. Esta tiene una CPU de cuatro núcleos (4 núcleos) que funciona a 1.5GHz, 2, 4 u 8GB de RAM, ethernet gigabit, WiFi, 2 puertos HDMI que soportan pantallas 4k, un puerto de salida de audio y video compuesto, puertos USB (2 USB 2.0, 2 USB 3.0), 40 pines GPIO, un conector para cámara para un módulo de cámara Raspberry Pi, y una ranura para tarjeta SD. Todo esto en una placa que mide 88mm x 58mm x 19.5mm y se alimenta con una fuente de alimentación USB-C de 3A. Estas comienzan en US$35, mucho más baratas que un PC o Mac. + +> 💁 También hay una Pi400, una computadora todo en uno con una Pi4 integrada en un teclado. + +![Un Raspberry Pi Zero](../../../../../translated_images/raspberry-pi-zero.f7a4133e1e7d54bb3dbb32319b217a53c5b94871995a54647f2894b54206b8d8.es.jpg) + +El Pi Zero es mucho más pequeño y de menor potencia. Tiene una CPU de un solo núcleo a 1GHz, 512MB de RAM, WiFi (en el modelo Zero W), un solo puerto HDMI, un puerto micro-USB, 40 pines GPIO, un conector para cámara para un módulo de cámara Raspberry Pi, y una ranura para tarjeta SD. Mide 65mm x 30mm x 5mm y consume muy poca energía. El Zero cuesta US$5, mientras que la versión W con WiFi cuesta US$10. + +> 🎓 Las CPUs en ambos dispositivos son procesadores ARM, a diferencia de los procesadores Intel/AMD x86 o x64 que encuentras en la mayoría de los PCs y Macs. Son similares a las CPUs que encuentras en algunos microcontroladores, así como en casi todos los teléfonos móviles, el Microsoft Surface X y los nuevos Macs basados en Apple Silicon. + +Todas las variantes de Raspberry Pi ejecutan una versión de Debian Linux llamada Raspberry Pi OS. Está disponible en una versión ligera sin escritorio, perfecta para proyectos 'headless' donde no necesitas una pantalla, o una versión completa con un entorno de escritorio completo, con navegador web, aplicaciones de oficina, herramientas de programación y juegos. Como el sistema operativo es una versión de Debian Linux, puedes instalar cualquier aplicación o herramienta que funcione en Debian y esté construida para el procesador ARM dentro del Pi. + +#### Tarea + +Investiga el Raspberry Pi. + +Si estás utilizando un Raspberry Pi para estas lecciones, lee sobre los diferentes componentes de hardware en la placa. + +* Puedes encontrar detalles sobre los procesadores utilizados en la [página de documentación de hardware de Raspberry Pi](https://www.raspberrypi.org/documentation/hardware/raspberrypi/). Lee sobre el procesador utilizado en el Pi que estás usando. +* Localiza los pines GPIO. Lee más sobre ellos en la [documentación GPIO de Raspberry Pi](https://www.raspberrypi.org/documentation/hardware/raspberrypi/gpio/README.md). Usa la [guía de uso de pines GPIO](https://www.raspberrypi.org/documentation/usage/gpio/README.md) para identificar los diferentes pines en tu Pi. + +### Programación de computadoras de placa única + +Las computadoras de placa única son computadoras completas que ejecutan un sistema operativo completo. Esto significa que hay una amplia gama de lenguajes de programación, frameworks y herramientas que puedes usar para programarlas, a diferencia de los microcontroladores que dependen del soporte de la placa en frameworks como Arduino. La mayoría de los lenguajes de programación tienen bibliotecas que pueden acceder a los pines GPIO para enviar y recibir datos de sensores y actuadores. + +✅ ¿Qué lenguajes de programación conoces? ¿Son compatibles con Linux? + +El lenguaje de programación más común para construir aplicaciones IoT en un Raspberry Pi es Python. Existe un enorme ecosistema de hardware diseñado para el Pi, y casi todos incluyen el código necesario para usarlos como bibliotecas de Python. Algunos de estos ecosistemas están basados en 'hats' (sombreros), llamados así porque se colocan encima del Pi como un sombrero y se conectan con un gran conector a los 40 pines GPIO. Estos hats proporcionan capacidades adicionales, como pantallas, sensores, autos controlados remotamente o adaptadores para conectar sensores con cables estandarizados. +### Uso de computadoras de placa única en implementaciones profesionales de IoT + +Las computadoras de placa única se utilizan en implementaciones profesionales de IoT, no solo como kits de desarrollo. Pueden ser una forma poderosa de controlar hardware y ejecutar tareas complejas, como modelos de aprendizaje automático. Por ejemplo, existe un [módulo de cómputo Raspberry Pi 4](https://www.raspberrypi.org/blog/raspberry-pi-compute-module-4/) que ofrece toda la potencia de una Raspberry Pi 4 pero en un formato compacto y más económico, sin la mayoría de los puertos, diseñado para ser instalado en hardware personalizado. + +--- + +## 🚀 Desafío + +El desafío de la última lección fue enumerar tantos dispositivos IoT como puedas que estén en tu hogar, escuela o lugar de trabajo. Para cada dispositivo en esta lista, ¿crees que están construidos alrededor de microcontroladores, computadoras de placa única o incluso una mezcla de ambos? + +## Cuestionario posterior a la lección + +[Cuestionario posterior a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/4) + +## Revisión y estudio autónomo + +* Lee la [guía de introducción a Arduino](https://www.arduino.cc/en/Guide/Introduction) para entender más sobre la plataforma Arduino. +* Lee la [introducción a la Raspberry Pi 4](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/) para aprender más sobre las Raspberry Pi. +* Aprende más sobre algunos de los conceptos y acrónimos en el artículo [¿Qué son los CPUs, MPUs, MCUs y GPUs? en la revista Electrical Engineering Journal](https://www.eejournal.com/article/what-the-faq-are-cpus-mpus-mcus-and-gpus/). + +✅ Utiliza estas guías, junto con los costos mostrados siguiendo los enlaces en la [guía de hardware](../../../hardware.md) para decidir qué plataforma de hardware deseas usar, o si prefieres usar un dispositivo virtual. + +## Tarea + +[Compara y contrasta microcontroladores y computadoras de placa única](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/2-deeper-dive/assignment.md b/translations/es/1-getting-started/lessons/2-deeper-dive/assignment.md new file mode 100644 index 00000000..0ced8b07 --- /dev/null +++ b/translations/es/1-getting-started/lessons/2-deeper-dive/assignment.md @@ -0,0 +1,26 @@ + +# Comparar y contrastar microcontroladores y computadoras de placa única + +## Instrucciones + +Esta lección cubrió microcontroladores y computadoras de placa única. Crea una tabla comparándolos y contrastándolos, y señala al menos 2 razones por las que usarías un microcontrolador en lugar de una computadora de placa única, y al menos 2 razones por las que usarías una computadora de placa única en lugar de un microcontrolador. + +## Rúbrica + +| Criterios | Ejemplar | Adecuado | Necesita Mejorar | +| --------- | -------- | -------- | ---------------- | +| Crear una tabla comparando microcontroladores con computadoras de placa única | Creó una lista con múltiples elementos que comparan y contrastan correctamente | Creó una lista con solo un par de elementos | Solo pudo identificar un elemento, o no pudo identificar elementos para comparar y contrastar | +| Razones para usar uno sobre el otro | Fue capaz de proporcionar 2 o más razones para los microcontroladores, y 2 o más para las computadoras de placa única | Solo pudo proporcionar 1-2 razones para un microcontrolador, y 1-2 razones para una computadora de placa única | No pudo proporcionar 1 o más razones para un microcontrolador o para una computadora de placa única | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/3-sensors-and-actuators/README.md b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/README.md new file mode 100644 index 00000000..369744d5 --- /dev/null +++ b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/README.md @@ -0,0 +1,230 @@ + +# Interactúa con el mundo físico con sensores y actuadores + +![Una vista general de esta lección en formato sketchnote](../../../../../translated_images/lesson-3.cc3b7b4cd646de598698cce043c0393fd62ef42bac2eaf60e61272cd844250f4.es.jpg) + +> Sketchnote por [Nitya Narasimhan](https://github.com/nitya). Haz clic en la imagen para una versión más grande. + +Esta lección fue impartida como parte de la [serie Hello IoT](https://youtube.com/playlist?list=PLmsFUfdnGr3xRts0TIwyaHyQuHaNQcb6-) del [Microsoft Reactor](https://developer.microsoft.com/reactor/?WT.mc_id=academic-17441-jabenn). La lección se enseñó en 2 videos: una clase de 1 hora y una sesión de preguntas y respuestas de 1 hora para profundizar en partes de la lección y responder preguntas. + +[![Lección 3: Interactúa con el mundo físico con sensores y actuadores](https://img.youtube.com/vi/Lqalu1v6aF4/0.jpg)](https://youtu.be/Lqalu1v6aF4) + +[![Lección 3: Interactúa con el mundo físico con sensores y actuadores - Horas de oficina](https://img.youtube.com/vi/qR3ekcMlLWA/0.jpg)](https://youtu.be/qR3ekcMlLWA) + +> 🎥 Haz clic en las imágenes de arriba para ver los videos + +## Cuestionario previo a la lección + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/5) + +## Introducción + +Esta lección introduce dos conceptos importantes para tu dispositivo IoT: sensores y actuadores. También trabajarás con ambos, añadiendo un sensor de luz a tu proyecto IoT y luego un LED controlado por niveles de luz, creando efectivamente una luz nocturna. + +En esta lección cubriremos: + +* [¿Qué son los sensores?](../../../../../1-getting-started/lessons/3-sensors-and-actuators) +* [Usar un sensor](../../../../../1-getting-started/lessons/3-sensors-and-actuators) +* [Tipos de sensores](../../../../../1-getting-started/lessons/3-sensors-and-actuators) +* [¿Qué son los actuadores?](../../../../../1-getting-started/lessons/3-sensors-and-actuators) +* [Usar un actuador](../../../../../1-getting-started/lessons/3-sensors-and-actuators) +* [Tipos de actuadores](../../../../../1-getting-started/lessons/3-sensors-and-actuators) + +## ¿Qué son los sensores? + +Los sensores son dispositivos de hardware que detectan el mundo físico, es decir, miden una o más propiedades a su alrededor y envían la información a un dispositivo IoT. Los sensores abarcan una amplia gama de dispositivos, ya que hay muchas cosas que se pueden medir, desde propiedades naturales como la temperatura del aire hasta interacciones físicas como el movimiento. + +Algunos sensores comunes incluyen: + +* Sensores de temperatura: detectan la temperatura del aire o la temperatura de lo que están inmersos. Para aficionados y desarrolladores, a menudo se combinan con presión de aire y humedad en un solo sensor. +* Botones: detectan cuando han sido presionados. +* Sensores de luz: detectan niveles de luz y pueden ser para colores específicos, luz UV, luz IR o luz visible en general. +* Cámaras: detectan una representación visual del mundo tomando una fotografía o transmitiendo video. +* Acelerómetros: detectan movimiento en múltiples direcciones. +* Micrófonos: detectan sonido, ya sea niveles generales de sonido o sonido direccional. + +✅ Investiga un poco. ¿Qué sensores tiene tu teléfono? + +Todos los sensores tienen algo en común: convierten lo que detectan en una señal eléctrica que puede ser interpretada por un dispositivo IoT. Cómo se interpreta esta señal eléctrica depende del sensor, así como del protocolo de comunicación utilizado para comunicarse con el dispositivo IoT. + +## Usar un sensor + +Sigue la guía correspondiente a continuación para añadir un sensor a tu dispositivo IoT: + +* [Arduino - Wio Terminal](wio-terminal-sensor.md) +* [Computadora de placa única - Raspberry Pi](pi-sensor.md) +* [Computadora de placa única - Dispositivo virtual](virtual-device-sensor.md) + +## Tipos de sensores + +Los sensores pueden ser analógicos o digitales. + +### Sensores analógicos + +Algunos de los sensores más básicos son analógicos. Estos sensores reciben un voltaje del dispositivo IoT, los componentes del sensor ajustan este voltaje, y el voltaje que regresa del sensor se mide para obtener el valor del sensor. + +> 🎓 El voltaje es una medida de cuánta fuerza hay para mover electricidad de un lugar a otro, como desde el terminal positivo de una batería al terminal negativo. Por ejemplo, una batería AA estándar es de 1.5V (V es el símbolo de voltios) y puede empujar electricidad con una fuerza de 1.5V desde su terminal positivo a su terminal negativo. Diferentes componentes eléctricos requieren diferentes voltajes para funcionar, por ejemplo, un LED puede iluminarse con entre 2-3V, pero una bombilla incandescente de 100W necesitaría 240V. Puedes leer más sobre voltaje en la [página de Voltaje en Wikipedia](https://wikipedia.org/wiki/Voltage). + +Un ejemplo de esto es un potenciómetro. Este es un dial que puedes girar entre dos posiciones y el sensor mide la rotación. + +![Un potenciómetro ajustado a un punto medio siendo enviado 5 voltios y devolviendo 3.8 voltios](../../../../../translated_images/potentiometer.35a348b9ce22f6ec1199ad37d68692d04185456ccbc2541a454bb6698be9f19c.es.png) + +El dispositivo IoT enviará una señal eléctrica al potenciómetro a un voltaje, como 5 voltios (5V). A medida que se ajusta el potenciómetro, cambia el voltaje que sale del otro lado. Imagina que tienes un potenciómetro etiquetado como un dial que va de 0 a [11](https://wikipedia.org/wiki/Up_to_eleven), como un control de volumen en un amplificador. Cuando el potenciómetro está en la posición completamente apagada (0), entonces saldrán 0V (0 voltios). Cuando está en la posición completamente encendida (11), saldrán 5V (5 voltios). + +> 🎓 Esto es una simplificación, y puedes leer más sobre potenciómetros y resistencias variables en la [página de Wikipedia sobre potenciómetros](https://wikipedia.org/wiki/Potentiometer). + +El voltaje que sale del sensor es leído por el dispositivo IoT, y el dispositivo puede responder a él. Dependiendo del sensor, este voltaje puede ser un valor arbitrario o puede mapearse a una unidad estándar. Por ejemplo, un sensor de temperatura analógico basado en un [termistor](https://wikipedia.org/wiki/Thermistor) cambia su resistencia dependiendo de la temperatura. El voltaje de salida puede luego convertirse en una temperatura en Kelvin, y correspondientemente en °C o °F, mediante cálculos en el código. + +✅ ¿Qué crees que sucede si el sensor devuelve un voltaje más alto del que se envió (por ejemplo, proveniente de una fuente de alimentación externa)? ⛔️ NO pruebes esto. + +#### Conversión de analógico a digital + +Los dispositivos IoT son digitales: no pueden trabajar con valores analógicos, solo trabajan con 0s y 1s. Esto significa que los valores de los sensores analógicos necesitan convertirse en una señal digital antes de que puedan ser procesados. Muchos dispositivos IoT tienen convertidores de analógico a digital (ADCs) para convertir entradas analógicas en representaciones digitales de su valor. Los sensores también pueden trabajar con ADCs a través de una placa conectora. Por ejemplo, en el ecosistema Seeed Grove con una Raspberry Pi, los sensores analógicos se conectan a puertos específicos en un 'hat' que se coloca sobre la Pi conectado a los pines GPIO de la Pi, y este hat tiene un ADC para convertir el voltaje en una señal digital que puede enviarse desde los pines GPIO de la Pi. + +Imagina que tienes un sensor de luz analógico conectado a un dispositivo IoT que usa 3.3V y está devolviendo un valor de 1V. Este 1V no significa nada en el mundo digital, por lo que necesita ser convertido. El voltaje será convertido a un valor analógico usando una escala dependiendo del dispositivo y sensor. Un ejemplo es el sensor de luz Seeed Grove que emite valores de 0 a 1,023. Para este sensor funcionando a 3.3V, una salida de 1V sería un valor de 300. Un dispositivo IoT no puede manejar 300 como un valor analógico, por lo que el valor sería convertido a `0000000100101100`, la representación binaria de 300 por el hat Grove. Esto luego sería procesado por el dispositivo IoT. + +✅ Si no conoces el sistema binario, investiga un poco para aprender cómo los números se representan con 0s y 1s. La [lección introductoria al sistema binario de BBC Bitesize](https://www.bbc.co.uk/bitesize/guides/zwsbwmn/revision/1) es un excelente lugar para comenzar. + +Desde una perspectiva de programación, todo esto generalmente es manejado por bibliotecas que vienen con los sensores, por lo que no necesitas preocuparte por esta conversión tú mismo. Para el sensor de luz Grove, usarías la biblioteca de Python y llamarías a la propiedad `light`, o usarías la biblioteca de Arduino y llamarías a `analogRead` para obtener un valor de 300. + +### Sensores digitales + +Los sensores digitales, al igual que los sensores analógicos, detectan el mundo que los rodea utilizando cambios en el voltaje eléctrico. La diferencia es que emiten una señal digital, ya sea midiendo solo dos estados o utilizando un ADC incorporado. Los sensores digitales son cada vez más comunes para evitar la necesidad de usar un ADC ya sea en una placa conectora o en el propio dispositivo IoT. + +El sensor digital más simple es un botón o interruptor. Este es un sensor con dos estados: encendido o apagado. + +![Un botón recibe 5 voltios. Cuando no se presiona devuelve 0 voltios, cuando se presiona devuelve 5 voltios](../../../../../translated_images/button.eadb560b77ac45e56f523d9d8876e40444f63b419e33eb820082d461fa79490b.es.png) + +Los pines en dispositivos IoT como los pines GPIO pueden medir esta señal directamente como un 0 o 1. Si el voltaje enviado es el mismo que el voltaje devuelto, el valor leído es 1; de lo contrario, el valor leído es 0. No hay necesidad de convertir la señal, solo puede ser 1 o 0. + +> 💁 Los voltajes nunca son exactos, especialmente porque los componentes en un sensor tendrán algo de resistencia, por lo que generalmente hay una tolerancia. Por ejemplo, los pines GPIO en una Raspberry Pi funcionan con 3.3V y leen una señal de retorno por encima de 1.8V como un 1, por debajo de 1.8V como 0. + +* 3.3V entran al botón. El botón está apagado, por lo que salen 0V, dando un valor de 0. +* 3.3V entran al botón. El botón está encendido, por lo que salen 3.3V, dando un valor de 1. + +Los sensores digitales más avanzados leen valores analógicos y luego los convierten utilizando ADCs integrados en señales digitales. Por ejemplo, un sensor de temperatura digital aún utilizará un termopar de la misma manera que un sensor analógico y aún medirá el cambio en el voltaje causado por la resistencia del termopar a la temperatura actual. En lugar de devolver un valor analógico y depender del dispositivo o placa conectora para convertirlo en una señal digital, un ADC incorporado en el sensor convertirá el valor y lo enviará como una serie de 0s y 1s al dispositivo IoT. Estos 0s y 1s se envían de la misma manera que la señal digital de un botón, con 1 siendo el voltaje completo y 0 siendo 0V. + +![Un sensor de temperatura digital convierte una lectura analógica en datos binarios con 0 como 0 voltios y 1 como 5 voltios antes de enviarlo a un dispositivo IoT](../../../../../translated_images/temperature-as-digital.85004491b977bae1129707df107c0b19fe6fc6374210e9027e04acb34a640c78.es.png) + +Enviar datos digitales permite que los sensores sean más complejos y envíen datos más detallados, incluso datos encriptados para sensores seguros. Un ejemplo es una cámara. Este es un sensor que captura una imagen y la envía como datos digitales que contienen esa imagen, generalmente en un formato comprimido como JPEG, para ser leído por el dispositivo IoT. Incluso puede transmitir video capturando imágenes y enviando ya sea el marco completo imagen por imagen o una transmisión de video comprimida. + +## ¿Qué son los actuadores? + +Los actuadores son lo opuesto a los sensores: convierten una señal eléctrica de tu dispositivo IoT en una interacción con el mundo físico, como emitir luz o sonido, o mover un motor. + +Algunos actuadores comunes incluyen: + +* LED: emiten luz cuando se encienden. +* Altavoz: emiten sonido basado en la señal enviada, desde un simple zumbador hasta un altavoz de audio que puede reproducir música. +* Motor paso a paso: convierten una señal en una cantidad definida de rotación, como girar un dial 90°. +* Relé: son interruptores que pueden encenderse o apagarse mediante una señal eléctrica. Permiten que un pequeño voltaje de un dispositivo IoT encienda voltajes más grandes. +* Pantallas: son actuadores más complejos y muestran información en una pantalla de múltiples segmentos. Las pantallas varían desde simples pantallas LED hasta monitores de video de alta resolución. + +✅ Investiga un poco. ¿Qué actuadores tiene tu teléfono? + +## Usar un actuador + +Sigue la guía correspondiente a continuación para añadir un actuador a tu dispositivo IoT, controlado por el sensor, para construir una luz nocturna IoT. Recogerá niveles de luz del sensor de luz y usará un actuador en forma de LED para emitir luz cuando el nivel de luz detectado sea demasiado bajo. + +![Un diagrama de flujo de la tarea que muestra los niveles de luz siendo leídos y verificados, y el LED siendo controlado](../../../../../translated_images/assignment-1-flow.7552a51acb1a5ec858dca6e855cdbb44206434006df8ba3799a25afcdab1665d.es.png) + +* [Arduino - Wio Terminal](wio-terminal-actuator.md) +* [Computadora de placa única - Raspberry Pi](pi-actuator.md) +* [Computadora de placa única - Dispositivo virtual](virtual-device-actuator.md) + +## Tipos de actuadores + +Al igual que los sensores, los actuadores pueden ser analógicos o digitales. + +### Actuadores analógicos + +Los actuadores analógicos toman una señal analógica y la convierten en algún tipo de interacción, donde la interacción cambia según el voltaje suministrado. + +Un ejemplo es una luz regulable, como las que podrías tener en tu casa. La cantidad de voltaje suministrado a la luz determina qué tan brillante es. +![Una luz atenuada con un voltaje bajo y más brillante con un voltaje más alto](../../../../../translated_images/dimmable-light.9ceffeb195dec1a849da718b2d71b32c35171ff7dfea9c07bbf82646a67acf6b.es.png) + +Al igual que con los sensores, el dispositivo IoT real funciona con señales digitales, no analógicas. Esto significa que, para enviar una señal analógica, el dispositivo IoT necesita un convertidor digital a analógico (DAC), ya sea directamente en el dispositivo IoT o en una placa de conexión. Esto convertirá los 0s y 1s del dispositivo IoT en un voltaje analógico que el actuador pueda usar. + +✅ ¿Qué crees que sucede si el dispositivo IoT envía un voltaje más alto del que el actuador puede manejar? +⛔️ NO pruebes esto. + +#### Modulación por Ancho de Pulso + +Otra opción para convertir señales digitales de un dispositivo IoT en una señal analógica es la modulación por ancho de pulso (PWM, por sus siglas en inglés). Esto implica enviar muchos pulsos digitales cortos que actúan como si fueran una señal analógica. + +Por ejemplo, puedes usar PWM para controlar la velocidad de un motor. + +Imagina que estás controlando un motor con un suministro de 5V. Envías un pulso corto a tu motor, cambiando el voltaje a alto (5V) durante dos centésimas de segundo (0.02s). En ese tiempo, tu motor puede girar una décima de vuelta, o 36°. Luego, la señal se detiene durante dos centésimas de segundo (0.02s), enviando una señal baja (0V). Cada ciclo de encendido y apagado dura 0.04s. El ciclo se repite. + +![Rotación de un motor con modulación por ancho de pulso a 150 RPM](../../../../../translated_images/pwm-motor-150rpm.83347ac04ca38482bd120939b133803963c9c15ca9d8d484712a4bd92820f6a4.es.png) + +Esto significa que en un segundo tienes 25 pulsos de 5V de 0.02s que hacen girar el motor, seguidos de 0.02s de pausa de 0V en los que el motor no gira. Cada pulso hace que el motor gire una décima de vuelta, lo que significa que el motor completa 2.5 vueltas por segundo. Has usado una señal digital para hacer girar el motor a 2.5 vueltas por segundo, o 150 [revoluciones por minuto](https://wikipedia.org/wiki/Revolutions_per_minute) (una medida no estándar de velocidad de rotación). + +```output +25 pulses per second x 0.1 rotations per pulse = 2.5 rotations per second +2.5 rotations per second x 60 seconds in a minute = 150rpm +``` + +> 🎓 Cuando una señal PWM está activa la mitad del tiempo y desactivada la otra mitad, se le llama [ciclo de trabajo del 50%](https://wikipedia.org/wiki/Duty_cycle). Los ciclos de trabajo se miden como el porcentaje de tiempo que la señal está en estado activo en comparación con el estado inactivo. + +![Rotación de un motor con modulación por ancho de pulso a 75 RPM](../../../../../translated_images/pwm-motor-75rpm.a5e4c939934b6e14fd9e98e4f2c9539d723da2b18f490eae0948dd044d18ff7e.es.png) + +Puedes cambiar la velocidad del motor ajustando el tamaño de los pulsos. Por ejemplo, con el mismo motor puedes mantener el mismo tiempo de ciclo de 0.04s, pero reducir el pulso activo a la mitad (0.01s) y aumentar el pulso inactivo a 0.03s. Tienes el mismo número de pulsos por segundo (25), pero cada pulso activo dura la mitad. Un pulso de la mitad de duración solo hace girar el motor una vigésima parte de una vuelta, y con 25 pulsos por segundo completará 1.25 vueltas por segundo o 75rpm. Al cambiar la duración de los pulsos de una señal digital, has reducido a la mitad la velocidad de un motor analógico. + +```output +25 pulses per second x 0.05 rotations per pulse = 1.25 rotations per second +1.25 rotations per second x 60 seconds in a minute = 75rpm +``` + +✅ ¿Cómo mantendrías la rotación del motor suave, especialmente a bajas velocidades? ¿Usarías un pequeño número de pulsos largos con pausas largas o muchos pulsos muy cortos con pausas muy cortas? + +> 💁 Algunos sensores también usan PWM para convertir señales analógicas en señales digitales. + +> 🎓 Puedes leer más sobre la modulación por ancho de pulso en la [página de Wikipedia sobre modulación por ancho de pulso](https://wikipedia.org/wiki/Pulse-width_modulation). + +### Actuadores digitales + +Los actuadores digitales, al igual que los sensores digitales, tienen dos estados controlados por un voltaje alto o bajo, o tienen un DAC incorporado que les permite convertir una señal digital en una analógica. + +Un actuador digital simple es un LED. Cuando un dispositivo envía una señal digital de 1, se envía un voltaje alto que enciende el LED. Cuando se envía una señal digital de 0, el voltaje cae a 0V y el LED se apaga. + +![Un LED está apagado a 0 voltios y encendido a 5V](../../../../../translated_images/led.ec6d94f66676a174ad06d9fa9ea49c2ee89beb18b312d5c6476467c66375b07f.es.png) + +✅ ¿Qué otros actuadores simples de dos estados se te ocurren? Un ejemplo es un solenoide, que es un electroimán que puede activarse para hacer cosas como mover un cerrojo de puerta para bloquear/desbloquear una puerta. + +Los actuadores digitales más avanzados, como las pantallas, requieren que los datos digitales se envíen en ciertos formatos. Por lo general, vienen con bibliotecas que facilitan el envío de los datos correctos para controlarlos. + +--- + +## 🚀 Desafío + +El desafío en las dos últimas lecciones fue enumerar tantos dispositivos IoT como puedas que estén en tu hogar, escuela o lugar de trabajo y decidir si están construidos alrededor de microcontroladores o computadoras de placa única, o incluso una mezcla de ambos. + +Para cada dispositivo que enumeraste, ¿a qué sensores y actuadores están conectados? ¿Cuál es el propósito de cada sensor y actuador conectado a estos dispositivos? + +## Cuestionario posterior a la lección + +[Cuestionario posterior a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/6) + +## Revisión y autoestudio + +* Lee sobre electricidad y circuitos en [ThingLearn](http://thinglearn.jenlooper.com/curriculum/). +* Lee sobre los diferentes tipos de sensores de temperatura en la [guía de sensores de temperatura de Seeed Studios](https://www.seeedstudio.com/blog/2019/10/14/temperature-sensors-for-arduino-projects/). +* Lee sobre LEDs en la [página de Wikipedia sobre LEDs](https://wikipedia.org/wiki/Light-emitting_diode). + +## Tarea + +[Investiga sensores y actuadores](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/3-sensors-and-actuators/assignment.md b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/assignment.md new file mode 100644 index 00000000..6e202137 --- /dev/null +++ b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/assignment.md @@ -0,0 +1,31 @@ + +# Investigar sensores y actuadores + +## Instrucciones + +Esta lección cubrió sensores y actuadores. Investiga y describe un sensor y un actuador que puedan usarse con un kit de desarrollo IoT, incluyendo: + +* Qué hace +* La electrónica/hardware que utiliza internamente +* Si es analógico o digital +* Cuáles son las unidades y el rango de entradas o mediciones + +## Rúbrica + +| Criterios | Ejemplar | Adecuado | Necesita Mejorar | +| --------- | --------- | -------- | ---------------- | +| Describir un sensor | Describió un sensor incluyendo detalles para las 4 secciones mencionadas anteriormente. | Describió un sensor, pero solo pudo proporcionar detalles de 2-3 de las secciones mencionadas anteriormente. | Describió un sensor, pero solo pudo proporcionar detalles de 1 de las secciones mencionadas anteriormente. | +| Describir un actuador | Describió un actuador incluyendo detalles para las 4 secciones mencionadas anteriormente. | Describió un actuador, pero solo pudo proporcionar detalles de 2-3 de las secciones mencionadas anteriormente. | Describió un actuador, pero solo pudo proporcionar detalles de 1 de las secciones mencionadas anteriormente. | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/3-sensors-and-actuators/pi-actuator.md b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/pi-actuator.md new file mode 100644 index 00000000..07b456ac --- /dev/null +++ b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/pi-actuator.md @@ -0,0 +1,130 @@ + +# Construye una luz nocturna - Raspberry Pi + +En esta parte de la lección, agregarás un LED a tu Raspberry Pi y lo usarás para crear una luz nocturna. + +## Hardware + +La luz nocturna ahora necesita un actuador. + +El actuador es un **LED**, un [diodo emisor de luz](https://wikipedia.org/wiki/Diodo_emisor_de_luz) que emite luz cuando la corriente fluye a través de él. Este es un actuador digital que tiene 2 estados: encendido y apagado. Enviar un valor de 1 enciende el LED, y un valor de 0 lo apaga. El LED es un actuador externo Grove y necesita conectarse al Grove Base hat en la Raspberry Pi. + +La lógica de la luz nocturna en pseudocódigo es: + +```output +Check the light level. +If the light is less than 300 + Turn the LED on +Otherwise + Turn the LED off +``` + +### Conecta el LED + +El LED Grove viene como un módulo con una selección de LEDs, lo que te permite elegir el color. + +#### Tarea - conecta el LED + +Conecta el LED. + +![Un LED Grove](../../../../../translated_images/grove-led.6c853be93f473cf2c439cfc74bb1064732b22251a83cedf66e62f783f9cc1a79.es.png) + +1. Elige tu LED favorito e inserta las patas en los dos agujeros del módulo LED. + + Los LEDs son diodos emisores de luz, y los diodos son dispositivos electrónicos que solo pueden conducir corriente en una dirección. Esto significa que el LED debe conectarse en la orientación correcta, de lo contrario, no funcionará. + + Una de las patas del LED es el pin positivo, y la otra es el pin negativo. El LED no es perfectamente redondo y es ligeramente más plano en un lado. El lado ligeramente más plano es el pin negativo. Cuando conectes el LED al módulo, asegúrate de que la pata del lado redondeado esté conectada al enchufe marcado con **+** en el exterior del módulo, y el lado más plano esté conectado al enchufe más cercano al centro del módulo. + +1. El módulo LED tiene un botón giratorio que te permite controlar el brillo. Gíralo completamente hacia arriba al principio, rotándolo en sentido antihorario hasta el tope, usando un destornillador pequeño de cabeza Phillips. + +1. Inserta un extremo de un cable Grove en el enchufe del módulo LED. Solo encajará en una dirección. + +1. Con la Raspberry Pi apagada, conecta el otro extremo del cable Grove al enchufe digital marcado como **D5** en el Grove Base hat conectado a la Pi. Este enchufe es el segundo desde la izquierda, en la fila de enchufes junto a los pines GPIO. + +![El LED Grove conectado al enchufe D5](../../../../../translated_images/pi-led.97f1d474981dc35d1c7996c7b17de355d3d0a6bc9606d79fa5f89df933415122.es.png) + +## Programa la luz nocturna + +Ahora se puede programar la luz nocturna usando el sensor de luz Grove y el LED Grove. + +### Tarea - programa la luz nocturna + +Programa la luz nocturna. + +1. Enciende la Raspberry Pi y espera a que arranque. + +1. Abre el proyecto de la luz nocturna en VS Code que creaste en la parte anterior de esta tarea, ya sea ejecutándolo directamente en la Pi o conectado usando la extensión Remote SSH. + +1. Agrega el siguiente código al archivo `app.py` para importar una biblioteca requerida. Esto debe añadirse al principio, debajo de las otras líneas `import`. + + ```python + from grove.grove_led import GroveLed + ``` + + La declaración `from grove.grove_led import GroveLed` importa el `GroveLed` de las bibliotecas de Python de Grove. Esta biblioteca contiene el código para interactuar con un LED Grove. + +1. Agrega el siguiente código después de la declaración de `light_sensor` para crear una instancia de la clase que gestiona el LED: + + ```python + led = GroveLed(5) + ``` + + La línea `led = GroveLed(5)` crea una instancia de la clase `GroveLed` conectada al pin **D5**, el pin digital Grove al que está conectado el LED. + + > 💁 Todos los enchufes tienen números de pin únicos. Los pines 0, 2, 4 y 6 son pines analógicos, mientras que los pines 5, 16, 18, 22, 24 y 26 son pines digitales. + +1. Agrega una verificación dentro del bucle `while`, y antes del `time.sleep`, para comprobar los niveles de luz y encender o apagar el LED: + + ```python + if light < 300: + led.on() + else: + led.off() + ``` + + Este código verifica el valor de `light`. Si es menor que 300, llama al método `on` de la clase `GroveLed`, que envía un valor digital de 1 al LED, encendiéndolo. Si el valor de luz es mayor o igual a 300, llama al método `off`, enviando un valor digital de 0 al LED, apagándolo. + + > 💁 Este código debe estar indentado al mismo nivel que la línea `print('Light level:', light)` para estar dentro del bucle while. + + > 💁 Al enviar valores digitales a los actuadores, un valor de 0 es 0V, y un valor de 1 es el voltaje máximo para el dispositivo. Para la Raspberry Pi con sensores y actuadores Grove, el voltaje de 1 es 3.3V. + +1. Desde el Terminal de VS Code, ejecuta lo siguiente para ejecutar tu aplicación en Python: + + ```sh + python3 app.py + ``` + + Los valores de luz se mostrarán en la consola. + + ```output + pi@raspberrypi:~/nightlight $ python3 app.py + Light level: 634 + Light level: 634 + Light level: 634 + Light level: 230 + Light level: 104 + Light level: 290 + ``` + +1. Cubre y descubre el sensor de luz. Observa cómo el LED se enciende si el nivel de luz es 300 o menos, y se apaga cuando el nivel de luz es mayor a 300. + + > 💁 Si el LED no se enciende, asegúrate de que esté conectado en la orientación correcta y que el botón giratorio esté ajustado al máximo. + +![El LED conectado a la Pi encendiéndose y apagándose según cambian los niveles de luz](../../../../../images/pi-running-assignment-1-1.gif) + +> 💁 Puedes encontrar este código en la carpeta [code-actuator/pi](../../../../../1-getting-started/lessons/3-sensors-and-actuators/code-actuator/pi). + +😀 ¡Tu programa de luz nocturna fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/3-sensors-and-actuators/pi-sensor.md b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/pi-sensor.md new file mode 100644 index 00000000..a82bf2ce --- /dev/null +++ b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/pi-sensor.md @@ -0,0 +1,110 @@ + +# Construir una luz nocturna - Raspberry Pi + +En esta parte de la lección, agregarás un sensor de luz a tu Raspberry Pi. + +## Hardware + +El sensor para esta lección es un **sensor de luz** que utiliza un [fotodiodo](https://wikipedia.org/wiki/Photodiode) para convertir la luz en una señal eléctrica. Este es un sensor analógico que envía un valor entero de 0 a 1,000 indicando una cantidad relativa de luz que no se corresponde con ninguna unidad estándar de medida como el [lux](https://wikipedia.org/wiki/Lux). + +El sensor de luz es un sensor Grove externo y necesita estar conectado al Grove Base hat en la Raspberry Pi. + +### Conectar el sensor de luz + +El sensor de luz Grove que se utiliza para detectar los niveles de luz debe estar conectado a la Raspberry Pi. + +#### Tarea - conectar el sensor de luz + +Conecta el sensor de luz. + +![Un sensor de luz Grove](../../../../../translated_images/grove-light-sensor.b8127b7c434e632d6bcdb57587a14e9ef69a268a22df95d08628f62b8fa5505c.es.png) + +1. Inserta un extremo de un cable Grove en el conector del módulo del sensor de luz. Solo encajará de una manera. + +1. Con la Raspberry Pi apagada, conecta el otro extremo del cable Grove al conector analógico marcado como **A0** en el Grove Base hat conectado a la Pi. Este conector es el segundo desde la derecha, en la fila de conectores junto a los pines GPIO. + +![El sensor de luz Grove conectado al conector A0](../../../../../translated_images/pi-light-sensor.66cc1e31fa48cd7d5f23400d4b2119aa41508275cb7c778053a7923b4e972d7e.es.png) + +## Programar el sensor de luz + +El dispositivo ahora puede ser programado utilizando el sensor de luz Grove. + +### Tarea - programar el sensor de luz + +Programa el dispositivo. + +1. Enciende la Pi y espera a que arranque. + +1. Abre el proyecto de luz nocturna en VS Code que creaste en la parte anterior de esta tarea, ya sea ejecutándolo directamente en la Pi o conectado mediante la extensión Remote SSH. + +1. Abre el archivo `app.py` y elimina todo el código que contiene. + +1. Agrega el siguiente código al archivo `app.py` para importar algunas bibliotecas necesarias: + + ```python + import time + from grove.grove_light_sensor_v1_2 import GroveLightSensor + ``` + + La declaración `import time` importa el módulo `time`, que se utilizará más adelante en esta tarea. + + La declaración `from grove.grove_light_sensor_v1_2 import GroveLightSensor` importa el `GroveLightSensor` de las bibliotecas de Python Grove. Esta biblioteca contiene el código para interactuar con un sensor de luz Grove y se instaló globalmente durante la configuración de la Pi. + +1. Agrega el siguiente código después del código anterior para crear una instancia de la clase que gestiona el sensor de luz: + + ```python + light_sensor = GroveLightSensor(0) + ``` + + La línea `light_sensor = GroveLightSensor(0)` crea una instancia de la clase `GroveLightSensor` conectándose al pin **A0**, el pin analógico Grove al que está conectado el sensor de luz. + +1. Agrega un bucle infinito después del código anterior para consultar el valor del sensor de luz y mostrarlo en la consola: + + ```python + while True: + light = light_sensor.light + print('Light level:', light) + ``` + + Esto leerá el nivel de luz actual en una escala de 0-1,023 utilizando la propiedad `light` de la clase `GroveLightSensor`. Esta propiedad lee el valor analógico del pin. Este valor se imprimirá en la consola. + +1. Agrega una pequeña pausa de un segundo al final del `loop`, ya que no es necesario verificar los niveles de luz continuamente. Una pausa reduce el consumo de energía del dispositivo. + + ```python + time.sleep(1) + ``` + +1. Desde el Terminal de VS Code, ejecuta lo siguiente para ejecutar tu aplicación de Python: + + ```sh + python3 app.py + ``` + + Los valores de luz se mostrarán en la consola. Cubre y descubre el sensor de luz, y los valores cambiarán: + + ```output + pi@raspberrypi:~/nightlight $ python3 app.py + Light level: 634 + Light level: 634 + Light level: 634 + Light level: 230 + Light level: 104 + Light level: 290 + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-sensor/pi](../../../../../1-getting-started/lessons/3-sensors-and-actuators/code-sensor/pi). + +😀 ¡Agregar un sensor a tu programa de luz nocturna fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/3-sensors-and-actuators/virtual-device-actuator.md b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/virtual-device-actuator.md new file mode 100644 index 00000000..7d87d48c --- /dev/null +++ b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/virtual-device-actuator.md @@ -0,0 +1,124 @@ + +# Construir una luz nocturna - Hardware IoT Virtual + +En esta parte de la lección, agregarás un LED a tu dispositivo IoT virtual y lo usarás para crear una luz nocturna. + +## Hardware Virtual + +La luz nocturna necesita un actuador, creado en la aplicación CounterFit. + +El actuador es un **LED**. En un dispositivo IoT físico, sería un [diodo emisor de luz](https://wikipedia.org/wiki/Light-emitting_diode) que emite luz cuando la corriente fluye a través de él. Este es un actuador digital que tiene 2 estados: encendido y apagado. Enviar un valor de 1 enciende el LED, y un valor de 0 lo apaga. + +La lógica de la luz nocturna en pseudocódigo es: + +```output +Check the light level. +If the light is less than 300 + Turn the LED on +Otherwise + Turn the LED off +``` + +### Agregar el actuador a CounterFit + +Para usar un LED virtual, necesitas agregarlo a la aplicación CounterFit. + +#### Tarea - agregar el actuador a CounterFit + +Agrega el LED a la aplicación CounterFit. + +1. Asegúrate de que la aplicación web CounterFit esté ejecutándose desde la parte anterior de esta tarea. Si no, iníciala y vuelve a agregar el sensor de luz. + +1. Crea un LED: + + 1. En el cuadro *Create actuator* en el panel *Actuator*, despliega el cuadro *Actuator type* y selecciona *LED*. + + 1. Configura el *Pin* en *5*. + + 1. Selecciona el botón **Add** para crear el LED en el Pin 5. + + ![Configuración del LED](../../../../../translated_images/counterfit-create-led.ba9db1c9b8c622a635d6dfae5cdc4e70c2b250635bd4f0601c6cf0bd22b7ba46.es.png) + + El LED será creado y aparecerá en la lista de actuadores. + + ![LED creado](../../../../../translated_images/counterfit-led.c0ab02de6d256ad84d9bad4d67a7faa709f0ea83e410cfe9b5561ef0cef30b1c.es.png) + + Una vez que el LED haya sido creado, puedes cambiar el color usando el selector *Color*. Selecciona el botón **Set** para cambiar el color después de haberlo seleccionado. + +### Programar la luz nocturna + +La luz nocturna ahora puede ser programada usando el sensor de luz y el LED de CounterFit. + +#### Tarea - programar la luz nocturna + +Programa la luz nocturna. + +1. Abre el proyecto de luz nocturna en VS Code que creaste en la parte anterior de esta tarea. Mata y vuelve a crear el terminal para asegurarte de que se esté ejecutando usando el entorno virtual si es necesario. + +1. Abre el archivo `app.py`. + +1. Agrega el siguiente código al archivo `app.py` para importar una biblioteca requerida. Esto debe ser agregado al principio, debajo de las otras líneas de `import`. + + ```python + from counterfit_shims_grove.grove_led import GroveLed + ``` + + La declaración `from counterfit_shims_grove.grove_led import GroveLed` importa el `GroveLed` de las bibliotecas shim de Python de CounterFit Grove. Esta biblioteca tiene código para interactuar con un LED creado en la aplicación CounterFit. + +1. Agrega el siguiente código después de la declaración de `light_sensor` para crear una instancia de la clase que gestiona el LED: + + ```python + led = GroveLed(5) + ``` + + La línea `led = GroveLed(5)` crea una instancia de la clase `GroveLed` conectándose al pin **5** - el pin de CounterFit Grove al que está conectado el LED. + +1. Agrega una verificación dentro del bucle `while`, y antes de `time.sleep`, para verificar los niveles de luz y encender o apagar el LED: + + ```python + if light < 300: + led.on() + else: + led.off() + ``` + + Este código verifica el valor de `light`. Si este es menor que 300, llama al método `on` de la clase `GroveLed`, que envía un valor digital de 1 al LED, encendiéndolo. Si el valor de luz es mayor o igual a 300, llama al método `off`, enviando un valor digital de 0 al LED, apagándolo. + + > 💁 Este código debe estar indentado al mismo nivel que la línea `print('Light level:', light)` para estar dentro del bucle while. + +1. Desde el terminal de VS Code, ejecuta lo siguiente para ejecutar tu aplicación de Python: + + ```sh + python3 app.py + ``` + + Los valores de luz serán mostrados en la consola. + + ```output + (.venv) ➜ GroveTest python3 app.py + Light level: 143 + Light level: 244 + Light level: 246 + Light level: 253 + ``` + +1. Cambia la configuración de *Value* o *Random* para variar el nivel de luz por encima y por debajo de 300. El LED se encenderá y apagará. + +![El LED en la aplicación CounterFit encendiéndose y apagándose a medida que cambia el nivel de luz](../../../../../images/virtual-device-running-assignment-1-1.gif) + +> 💁 Puedes encontrar este código en la carpeta [code-actuator/virtual-device](../../../../../1-getting-started/lessons/3-sensors-and-actuators/code-actuator/virtual-device). + +😀 ¡Tu programa de luz nocturna fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/3-sensors-and-actuators/virtual-device-sensor.md b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/virtual-device-sensor.md new file mode 100644 index 00000000..91419bf2 --- /dev/null +++ b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/virtual-device-sensor.md @@ -0,0 +1,124 @@ + +# Construir una luz nocturna - Hardware IoT Virtual + +En esta parte de la lección, agregarás un sensor de luz a tu dispositivo IoT virtual. + +## Hardware Virtual + +La luz nocturna necesita un sensor, creado en la aplicación CounterFit. + +El sensor es un **sensor de luz**. En un dispositivo IoT físico, sería un [fotodiodo](https://wikipedia.org/wiki/Photodiode) que convierte la luz en una señal eléctrica. Los sensores de luz son sensores analógicos que envían un valor entero indicando una cantidad relativa de luz, que no se corresponde con ninguna unidad estándar de medida como el [lux](https://wikipedia.org/wiki/Lux). + +### Agregar los sensores a CounterFit + +Para usar un sensor de luz virtual, necesitas agregarlo a la aplicación CounterFit. + +#### Tarea - agregar los sensores a CounterFit + +Agrega el sensor de luz a la aplicación CounterFit. + +1. Asegúrate de que la aplicación web CounterFit esté ejecutándose desde la parte anterior de esta tarea. Si no, iníciala. + +1. Crea un sensor de luz: + + 1. En el cuadro *Create sensor* en el panel *Sensors*, despliega el cuadro *Sensor type* y selecciona *Light*. + + 1. Deja las *Units* configuradas como *NoUnits*. + + 1. Asegúrate de que el *Pin* esté configurado como *0*. + + 1. Selecciona el botón **Add** para crear el sensor de luz en el Pin 0. + + ![Configuración del sensor de luz](../../../../../translated_images/counterfit-create-light-sensor.9f36a5e0d4458d8d554d54b34d2c806d56093d6e49fddcda2d20f6fef7f5cce1.es.png) + + El sensor de luz será creado y aparecerá en la lista de sensores. + + ![Sensor de luz creado](../../../../../translated_images/counterfit-light-sensor.5d0f5584df56b90f6b2561910d9cb20dfbd73eeff2177c238d38f4de54aefae1.es.png) + +## Programar el sensor de luz + +El dispositivo ahora puede ser programado para usar el sensor de luz integrado. + +### Tarea - programar el sensor de luz + +Programa el dispositivo. + +1. Abre el proyecto de luz nocturna en VS Code que creaste en la parte anterior de esta tarea. Mata y vuelve a crear el terminal para asegurarte de que se esté ejecutando usando el entorno virtual si es necesario. + +1. Abre el archivo `app.py`. + +1. Agrega el siguiente código en la parte superior del archivo `app.py` junto con el resto de las declaraciones `import` para importar algunas bibliotecas necesarias: + + ```python + import time + from counterfit_shims_grove.grove_light_sensor_v1_2 import GroveLightSensor + ``` + + La declaración `import time` importa el módulo `time` de Python que se usará más adelante en esta tarea. + + La declaración `from counterfit_shims_grove.grove_light_sensor_v1_2 import GroveLightSensor` importa el `GroveLightSensor` de las bibliotecas Python de CounterFit Grove shim. Esta biblioteca tiene código para interactuar con un sensor de luz creado en la aplicación CounterFit. + +1. Agrega el siguiente código al final del archivo para crear instancias de clases que gestionan el sensor de luz: + + ```python + light_sensor = GroveLightSensor(0) + ``` + + La línea `light_sensor = GroveLightSensor(0)` crea una instancia de la clase `GroveLightSensor` conectándose al pin **0** - el pin de CounterFit Grove al que está conectado el sensor de luz. + +1. Agrega un bucle infinito después del código anterior para consultar el valor del sensor de luz y mostrarlo en la consola: + + ```python + while True: + light = light_sensor.light + print('Light level:', light) + ``` + + Esto leerá el nivel de luz actual usando la propiedad `light` de la clase `GroveLightSensor`. Esta propiedad lee el valor analógico del pin. Este valor luego se imprime en la consola. + +1. Agrega una pequeña pausa de un segundo al final del bucle `while`, ya que no es necesario verificar los niveles de luz continuamente. Una pausa reduce el consumo de energía del dispositivo. + + ```python + time.sleep(1) + ``` + +1. Desde el terminal de VS Code, ejecuta lo siguiente para ejecutar tu aplicación de Python: + + ```sh + python3 app.py + ``` + + Los valores de luz se mostrarán en la consola. Inicialmente este valor será 0. + +1. Desde la aplicación CounterFit, cambia el valor del sensor de luz que será leído por la aplicación. Puedes hacerlo de dos maneras: + + * Ingresa un número en el cuadro *Value* del sensor de luz y luego selecciona el botón **Set**. El número que ingreses será el valor devuelto por el sensor. + + * Marca la casilla *Random* y escribe un valor *Min* y *Max*, luego selecciona el botón **Set**. Cada vez que el sensor lea un valor, leerá un número aleatorio entre *Min* y *Max*. + + Los valores que configures se mostrarán en la consola. Cambia el *Value* o la configuración *Random* para que el valor cambie. + + ```output + (.venv) ➜ GroveTest python3 app.py + Light level: 143 + Light level: 244 + Light level: 246 + Light level: 253 + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-sensor/virtual-device](../../../../../1-getting-started/lessons/3-sensors-and-actuators/code-sensor/virtual-device). + +😀 ¡Tu programa de luz nocturna fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/3-sensors-and-actuators/wio-terminal-actuator.md b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/wio-terminal-actuator.md new file mode 100644 index 00000000..98ffa528 --- /dev/null +++ b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/wio-terminal-actuator.md @@ -0,0 +1,124 @@ + +# Construye una luz nocturna - Wio Terminal + +En esta parte de la lección, agregarás un LED a tu Wio Terminal y lo usarás para crear una luz nocturna. + +## Hardware + +La luz nocturna ahora necesita un actuador. + +El actuador es un **LED**, un [diodo emisor de luz](https://wikipedia.org/wiki/Light-emitting_diode) que emite luz cuando la corriente pasa a través de él. Este es un actuador digital que tiene dos estados: encendido y apagado. Enviar un valor de 1 enciende el LED, y un valor de 0 lo apaga. Este es un actuador externo Grove y necesita conectarse al Wio Terminal. + +La lógica de la luz nocturna en pseudocódigo es: + +```output +Check the light level. +If the light is less than 300 + Turn the LED on +Otherwise + Turn the LED off +``` + +### Conecta el LED + +El Grove LED viene como un módulo con una selección de LEDs, permitiéndote elegir el color. + +#### Tarea - conecta el LED + +Conecta el LED. + +![Un Grove LED](../../../../../translated_images/grove-led.6c853be93f473cf2c439cfc74bb1064732b22251a83cedf66e62f783f9cc1a79.es.png) + +1. Elige tu LED favorito e inserta las patas en los dos agujeros del módulo LED. + + Los LEDs son diodos emisores de luz, y los diodos son dispositivos electrónicos que solo pueden conducir corriente en una dirección. Esto significa que el LED debe conectarse en la orientación correcta, de lo contrario no funcionará. + + Una de las patas del LED es el pin positivo, la otra es el pin negativo. El LED no es perfectamente redondo y es ligeramente más plano en un lado. El lado más plano es el pin negativo. Cuando conectes el LED al módulo, asegúrate de que la pata del lado redondeado esté conectada al enchufe marcado con **+** en el exterior del módulo, y el lado más plano esté conectado al enchufe más cercano al centro del módulo. + +1. El módulo LED tiene un botón giratorio que te permite controlar el brillo. Gíralo completamente hacia arriba al principio, rotándolo en sentido antihorario hasta que no pueda girar más usando un pequeño destornillador de cabeza Phillips. + +1. Inserta un extremo de un cable Grove en el enchufe del módulo LED. Solo entrará en una dirección. + +1. Con el Wio Terminal desconectado de tu computadora u otra fuente de alimentación, conecta el otro extremo del cable Grove al enchufe Grove del lado derecho del Wio Terminal mientras miras la pantalla. Este es el enchufe más alejado del botón de encendido. + + > 💁 El enchufe Grove del lado derecho puede usarse con sensores y actuadores analógicos o digitales. El enchufe del lado izquierdo es solo para sensores y actuadores digitales. C se cubrirá en una lección posterior. + +![El Grove LED conectado al enchufe del lado derecho](../../../../../translated_images/wio-led.265a1897e72d7f21c753257516a4b677d8e30ce2b95fee98189458b3275ba0a6.es.png) + +## Programa la luz nocturna + +La luz nocturna ahora puede programarse usando el sensor de luz incorporado y el Grove LED. + +### Tarea - programa la luz nocturna + +Programa la luz nocturna. + +1. Abre el proyecto de luz nocturna en VS Code que creaste en la parte anterior de esta asignación. + +1. Agrega la siguiente línea al final de la función `setup`: + + ```cpp + pinMode(D0, OUTPUT); + ``` + + Esta línea configura el pin utilizado para comunicarse con el LED a través del puerto Grove. + + El pin `D0` es el pin digital para el enchufe Grove del lado derecho. Este pin se configura como `OUTPUT`, lo que significa que se conecta a un actuador y se escribirán datos en el pin. + +1. Agrega el siguiente código inmediatamente antes del `delay` en la función loop: + + ```cpp + if (light < 300) + { + digitalWrite(D0, HIGH); + } + else + { + digitalWrite(D0, LOW); + } + ``` + + Este código verifica el valor de `light`. Si es menor que 300, envía un valor `HIGH` al pin digital `D0`. Este `HIGH` es un valor de 1, encendiendo el LED. Si el valor de luz es mayor o igual a 300, se envía un valor `LOW` de 0 al pin, apagando el LED. + + > 💁 Al enviar valores digitales a actuadores, un valor LOW es 0v, y un valor HIGH es el voltaje máximo para el dispositivo. Para el Wio Terminal, el voltaje HIGH es 3.3V. + +1. Reconecta el Wio Terminal a tu computadora y sube el nuevo código como lo hiciste antes. + +1. Conecta el Monitor Serial. Los valores de luz se mostrarán en el terminal. + + ```output + > Executing task: platformio device monitor < + + --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time + --- More details at http://bit.ly/pio-monitor-filters + --- Miniterm on /dev/cu.usbmodem101 9600,8,N,1 --- + --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + Light value: 4 + Light value: 5 + Light value: 4 + Light value: 158 + Light value: 343 + Light value: 348 + Light value: 344 + ``` + +1. Cubre y descubre el sensor de luz. Observa cómo el LED se enciende si el nivel de luz es 300 o menos, y se apaga cuando el nivel de luz es mayor a 300. + +![El LED conectado al WIO encendiéndose y apagándose según cambia el nivel de luz](../../../../../images/wio-running-assignment-1-1.gif) + +> 💁 Puedes encontrar este código en la carpeta [code-actuator/wio-terminal](../../../../../1-getting-started/lessons/3-sensors-and-actuators/code-actuator/wio-terminal). + +😀 ¡Tu programa de luz nocturna fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/3-sensors-and-actuators/wio-terminal-sensor.md b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/wio-terminal-sensor.md new file mode 100644 index 00000000..0c06778a --- /dev/null +++ b/translations/es/1-getting-started/lessons/3-sensors-and-actuators/wio-terminal-sensor.md @@ -0,0 +1,87 @@ + +# Agregar un sensor - Wio Terminal + +En esta parte de la lección, usarás el sensor de luz en tu Wio Terminal. + +## Hardware + +El sensor para esta lección es un **sensor de luz** que utiliza un [fotodiodo](https://wikipedia.org/wiki/Photodiode) para convertir la luz en una señal eléctrica. Este es un sensor analógico que envía un valor entero de 0 a 1,023 indicando una cantidad relativa de luz que no se corresponde con ninguna unidad estándar de medida como [lux](https://wikipedia.org/wiki/Lux). + +El sensor de luz está integrado en el Wio Terminal y es visible a través de la ventana de plástico transparente en la parte trasera. + +![El sensor de luz en la parte trasera del Wio Terminal](../../../../../translated_images/wio-light-sensor.b1f529f3c95f51654f2e2c1d2d4b55fe547d189f588c974f5c2462c728133840.es.png) + +## Programar el sensor de luz + +Ahora se puede programar el dispositivo para usar el sensor de luz integrado. + +### Tarea + +Programa el dispositivo. + +1. Abre el proyecto de luz nocturna en VS Code que creaste en la parte anterior de esta tarea. + +1. Agrega la siguiente línea al final de la función `setup`: + + ```cpp + pinMode(WIO_LIGHT, INPUT); + ``` + + Esta línea configura los pines utilizados para comunicarse con el hardware del sensor. + + El pin `WIO_LIGHT` es el número del pin GPIO conectado al sensor de luz integrado. Este pin se configura como `INPUT`, lo que significa que se conecta a un sensor y se leerán datos desde el pin. + +1. Elimina el contenido de la función `loop`. + +1. Agrega el siguiente código a la función `loop`, que ahora está vacía. + + ```cpp + int light = analogRead(WIO_LIGHT); + Serial.print("Light value: "); + Serial.println(light); + ``` + + Este código lee un valor analógico del pin `WIO_LIGHT`. Esto lee un valor de 0-1,023 del sensor de luz integrado. Este valor luego se envía al puerto serial para que puedas leerlo en el Monitor Serial cuando este código esté en ejecución. `Serial.print` escribe el texto sin un salto de línea al final, por lo que cada línea comenzará con `Light value:` y terminará con el valor real de luz. + +1. Agrega un pequeño retraso de un segundo (1,000ms) al final del `loop`, ya que no es necesario verificar los niveles de luz de manera continua. Un retraso reduce el consumo de energía del dispositivo. + + ```cpp + delay(1000); + ``` + +1. Reconecta el Wio Terminal a tu computadora y sube el nuevo código como lo hiciste antes. + +1. Conecta el Monitor Serial. Los valores de luz se mostrarán en el terminal. Cubre y descubre el sensor de luz en la parte trasera del Wio Terminal, y los valores cambiarán. + + ```output + > Executing task: platformio device monitor < + + --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time + --- More details at http://bit.ly/pio-monitor-filters + --- Miniterm on /dev/cu.usbmodem101 9600,8,N,1 --- + --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + Light value: 4 + Light value: 5 + Light value: 4 + Light value: 158 + Light value: 343 + Light value: 348 + Light value: 344 + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-sensor/wio-terminal](../../../../../1-getting-started/lessons/3-sensors-and-actuators/code-sensor/wio-terminal). + +😀 ¡Agregar un sensor a tu programa de luz nocturna fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/4-connect-internet/README.md b/translations/es/1-getting-started/lessons/4-connect-internet/README.md new file mode 100644 index 00000000..188c1139 --- /dev/null +++ b/translations/es/1-getting-started/lessons/4-connect-internet/README.md @@ -0,0 +1,466 @@ + +# Conecta tu dispositivo a Internet + +![Un resumen visual de esta lección](../../../../../translated_images/lesson-4.7344e074ea68fa545fd320b12dce36d72dd62d28c3b4596cb26cf315f434b98f.es.jpg) + +> Resumen visual por [Nitya Narasimhan](https://github.com/nitya). Haz clic en la imagen para verla en tamaño completo. + +Esta lección fue impartida como parte de la serie [Hello IoT](https://youtube.com/playlist?list=PLmsFUfdnGr3xRts0TIwyaHyQuHaNQcb6-) del [Microsoft Reactor](https://developer.microsoft.com/reactor/?WT.mc_id=academic-17441-jabenn). La lección se presentó en 2 videos: una clase de 1 hora y una sesión de preguntas y respuestas de 1 hora para profundizar en partes de la lección y responder preguntas. + +[![Lección 4: Conecta tu dispositivo a Internet](https://img.youtube.com/vi/O4dd172mZhs/0.jpg)](https://youtu.be/O4dd172mZhs) + +[![Lección 4: Conecta tu dispositivo a Internet - Sesión de preguntas](https://img.youtube.com/vi/j-cVCzRDE2Q/0.jpg)](https://youtu.be/j-cVCzRDE2Q) + +> 🎥 Haz clic en las imágenes de arriba para ver los videos + +## Cuestionario previo a la lección + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/7) + +## Introducción + +La **I** en IoT significa **Internet**: la conectividad en la nube y los servicios que habilitan muchas de las funciones de los dispositivos IoT, desde recopilar mediciones de los sensores conectados al dispositivo hasta enviar mensajes para controlar los actuadores. Los dispositivos IoT suelen conectarse a un único servicio IoT en la nube utilizando un protocolo de comunicación estándar, y ese servicio está conectado al resto de tu aplicación IoT, desde servicios de inteligencia artificial para tomar decisiones inteligentes basadas en tus datos, hasta aplicaciones web para control o generación de informes. + +> 🎓 Los datos recopilados de los sensores y enviados a la nube se llaman telemetría. + +Los dispositivos IoT pueden recibir mensajes desde la nube. A menudo, estos mensajes contienen comandos, es decir, instrucciones para realizar una acción, ya sea internamente (como reiniciar o actualizar el firmware) o utilizando un actuador (como encender una luz). + +Esta lección introduce algunos de los protocolos de comunicación que los dispositivos IoT pueden usar para conectarse a la nube y los tipos de datos que podrían enviar o recibir. También tendrás la oportunidad de trabajar con ellos, añadiendo control por Internet a tu luz nocturna y moviendo la lógica de control del LED al código 'servidor' que se ejecuta localmente. + +En esta lección cubriremos: + +* [Protocolos de comunicación](../../../../../1-getting-started/lessons/4-connect-internet) +* [Transporte de Telemetría en Cola de Mensajes (MQTT)](../../../../../1-getting-started/lessons/4-connect-internet) +* [Telemetría](../../../../../1-getting-started/lessons/4-connect-internet) +* [Comandos](../../../../../1-getting-started/lessons/4-connect-internet) + +## Protocolos de comunicación + +Existen varios protocolos de comunicación populares que los dispositivos IoT utilizan para comunicarse con Internet. Los más comunes se basan en la mensajería de publicación/suscripción a través de algún tipo de intermediario. Los dispositivos IoT se conectan al intermediario, publican telemetría y se suscriben a comandos. Los servicios en la nube también se conectan al intermediario, se suscriben a todos los mensajes de telemetría y publican comandos, ya sea para dispositivos específicos o para grupos de dispositivos. + +![Los dispositivos IoT se conectan a un intermediario, publican telemetría y se suscriben a comandos. Los servicios en la nube se conectan al intermediario, se suscriben a toda la telemetría y envían comandos a dispositivos específicos.](../../../../../translated_images/pub-sub.7c7ed43fe9fd15d4e1f81a3fd95440413c457acd9bcbe9a43341e30e88db5264.es.png) + +MQTT es el protocolo de comunicación más popular para dispositivos IoT y se cubre en esta lección. Otros protocolos incluyen AMQP y HTTP/HTTPS. + +## Transporte de Telemetría en Cola de Mensajes (MQTT) + +[MQTT](http://mqtt.org) es un protocolo de mensajería ligero y de estándar abierto que puede enviar mensajes entre dispositivos. Fue diseñado en 1999 para monitorear oleoductos, antes de ser liberado como estándar abierto 15 años después por IBM. + +MQTT tiene un único intermediario y múltiples clientes. Todos los clientes se conectan al intermediario, y este enruta los mensajes a los clientes relevantes. Los mensajes se enrutan utilizando temas nombrados, en lugar de enviarse directamente a un cliente individual. Un cliente puede publicar en un tema, y cualquier cliente que se suscriba a ese tema recibirá el mensaje. + +![Dispositivo IoT publicando telemetría en el tema /telemetry, y el servicio en la nube suscribiéndose a ese tema](../../../../../translated_images/mqtt.cbf7f21d9adc3e17548b359444cc11bb4bf2010543e32ece9a47becf54438c23.es.png) + +✅ Investiga. Si tienes muchos dispositivos IoT, ¿cómo puedes asegurarte de que tu intermediario MQTT pueda manejar todos los mensajes? + +### Conecta tu dispositivo IoT a MQTT + +La primera parte para añadir control por Internet a tu luz nocturna es conectarla a un intermediario MQTT. + +#### Tarea + +Conecta tu dispositivo a un intermediario MQTT. + +En esta parte de la lección, conectarás tu luz nocturna IoT a Internet para permitir que sea controlada de forma remota. Más adelante en esta lección, tu dispositivo IoT enviará un mensaje de telemetría a través de MQTT a un intermediario MQTT público con el nivel de luz, donde será recogido por un código de servidor que escribirás. Este código verificará el nivel de luz y enviará un mensaje de comando de vuelta al dispositivo indicándole que encienda o apague el LED. + +El caso de uso real para una configuración como esta podría ser recopilar datos de múltiples sensores de luz antes de decidir encender las luces en un lugar con muchas luces, como un estadio. Esto podría evitar que las luces se enciendan si solo un sensor está cubierto por nubes o un pájaro, pero los otros sensores detectan suficiente luz. + +✅ ¿Qué otras situaciones requerirían evaluar datos de múltiples sensores antes de enviar comandos? + +En lugar de lidiar con las complejidades de configurar un intermediario MQTT como parte de esta tarea, puedes usar un servidor de prueba público que ejecuta [Eclipse Mosquitto](https://www.mosquitto.org), un intermediario MQTT de código abierto. Este intermediario de prueba está disponible públicamente en [test.mosquitto.org](https://test.mosquitto.org) y no requiere configurar una cuenta, lo que lo convierte en una excelente herramienta para probar clientes y servidores MQTT. + +> 💁 Este intermediario de prueba es público y no seguro. Cualquiera podría estar escuchando lo que publicas, por lo que no debe usarse con datos que necesiten mantenerse privados. + +![Un diagrama de flujo de la tarea mostrando los niveles de luz siendo leídos y verificados, y el LED siendo controlado](../../../../../translated_images/assignment-1-internet-flow.3256feab5f052fd273bf4e331157c574c2c3fa42e479836fc9c3586f41db35a5.es.png) + +Sigue el paso relevante a continuación para conectar tu dispositivo al intermediario MQTT: + +* [Arduino - Wio Terminal](wio-terminal-mqtt.md) +* [Computadora de placa única - Raspberry Pi/Dispositivo IoT virtual](single-board-computer-mqtt.md) + +### Una mirada más profunda a MQTT + +Los temas pueden tener una jerarquía, y los clientes pueden suscribirse a diferentes niveles de la jerarquía utilizando comodines. Por ejemplo, puedes enviar mensajes de telemetría de temperatura al tema `/telemetry/temperature` y mensajes de humedad al tema `/telemetry/humidity`, luego en tu aplicación en la nube suscribirte al tema `/telemetry/*` para recibir tanto los mensajes de telemetría de temperatura como los de humedad. + +Los mensajes pueden enviarse con una calidad de servicio (QoS), que determina la garantía de que el mensaje sea recibido. + +* Una vez como máximo: el mensaje se envía solo una vez y el cliente y el intermediario no toman medidas adicionales para confirmar la entrega (enviar y olvidar). +* Al menos una vez: el mensaje se reintenta varias veces por el remitente hasta que se recibe una confirmación (entrega confirmada). +* Exactamente una vez: el remitente y el receptor realizan un proceso de dos niveles para garantizar que solo se reciba una copia del mensaje (entrega asegurada). + +✅ ¿Qué situaciones podrían requerir un mensaje de entrega asegurada en lugar de un mensaje de enviar y olvidar? + +Aunque el nombre es Transporte de Telemetría en Cola de Mensajes (MQTT), en realidad no admite colas de mensajes. Esto significa que si un cliente se desconecta y luego se vuelve a conectar, no recibirá mensajes enviados durante la desconexión, excepto aquellos mensajes que ya había comenzado a procesar utilizando el proceso de QoS. Los mensajes pueden tener una bandera de retención configurada. Si esta está configurada, el intermediario MQTT almacenará el último mensaje enviado en un tema con esta bandera y lo enviará a cualquier cliente que se suscriba posteriormente al tema. De esta manera, los clientes siempre recibirán el último mensaje. + +MQTT también admite una función de mantener vivo que verifica si la conexión sigue activa durante largos intervalos entre mensajes. + +> 🦟 [Mosquitto de la Fundación Eclipse](https://mosquitto.org) tiene un intermediario MQTT gratuito que puedes ejecutar tú mismo para experimentar con MQTT, junto con un intermediario MQTT público que puedes usar para probar tu código, alojado en [test.mosquitto.org](https://test.mosquitto.org). + +Las conexiones MQTT pueden ser públicas y abiertas, o encriptadas y seguras utilizando nombres de usuario y contraseñas, o certificados. + +> 💁 MQTT se comunica sobre TCP/IP, el mismo protocolo de red subyacente que HTTP, pero en un puerto diferente. También puedes usar MQTT sobre websockets para comunicarte con aplicaciones web que se ejecutan en un navegador, o en situaciones donde los firewalls u otras reglas de red bloquean las conexiones MQTT estándar. + +## Telemetría + +La palabra telemetría proviene de raíces griegas que significan medir de forma remota. La telemetría es el acto de recopilar datos de sensores y enviarlos a la nube. + +> 💁 Uno de los primeros dispositivos de telemetría fue inventado en Francia en 1874 y enviaba datos en tiempo real sobre el clima y la profundidad de la nieve desde Mont Blanc a París. Utilizaba cables físicos, ya que las tecnologías inalámbricas no estaban disponibles en ese momento. + +Volvamos al ejemplo del termostato inteligente de la Lección 1. + +![Un termostato conectado a Internet utilizando múltiples sensores de habitación](../../../../../translated_images/telemetry.21e5d8b97649d2ebeb0f68d4b9691ab2d1f7bd629338e131465aff8a614e4d4a.es.png) + +El termostato tiene sensores de temperatura para recopilar telemetría. Lo más probable es que tenga un sensor de temperatura incorporado, y podría conectarse a múltiples sensores de temperatura externos a través de un protocolo inalámbrico como [Bluetooth Low Energy](https://wikipedia.org/wiki/Bluetooth_Low_Energy) (BLE). + +Un ejemplo de los datos de telemetría que enviaría podría ser: + +| Nombre | Valor | Descripción | +| ------ | ----- | ----------- | +| `thermostat_temperature` | 18°C | La temperatura medida por el sensor de temperatura incorporado del termostato | +| `livingroom_temperature` | 19°C | La temperatura medida por un sensor de temperatura remoto que ha sido nombrado `livingroom` para identificar la habitación en la que se encuentra | +| `bedroom_temperature` | 21°C | La temperatura medida por un sensor de temperatura remoto que ha sido nombrado `bedroom` para identificar la habitación en la que se encuentra | + +El servicio en la nube puede usar estos datos de telemetría para tomar decisiones sobre qué comandos enviar para controlar la calefacción. + +### Envía telemetría desde tu dispositivo IoT + +La siguiente parte para añadir control por Internet a tu luz nocturna es enviar la telemetría del nivel de luz al intermediario MQTT en un tema de telemetría. + +#### Tarea - envía telemetría desde tu dispositivo IoT + +Envía telemetría del nivel de luz al intermediario MQTT. + +Los datos se envían codificados como JSON, abreviatura de JavaScript Object Notation, un estándar para codificar datos en texto utilizando pares clave/valor. + +✅ Si no has trabajado con JSON antes, puedes aprender más sobre él en la [documentación de JSON.org](https://www.json.org/). + +Sigue el paso relevante a continuación para enviar telemetría desde tu dispositivo al intermediario MQTT: + +* [Arduino - Wio Terminal](wio-terminal-telemetry.md) +* [Computadora de placa única - Raspberry Pi/Dispositivo IoT virtual](single-board-computer-telemetry.md) + +### Recibe telemetría del intermediario MQTT + +No tiene sentido enviar telemetría si no hay nada en el otro extremo para escucharla. La telemetría del nivel de luz necesita algo que la escuche para procesar los datos. Este código 'servidor' es el tipo de código que implementarás en un servicio en la nube como parte de una aplicación IoT más grande, pero aquí vas a ejecutar este código localmente en tu computadora (o en tu Pi si estás programando directamente allí). El código del servidor consiste en una aplicación Python que escucha mensajes de telemetría a través de MQTT con niveles de luz. Más adelante en esta lección, harás que responda con un mensaje de comando con instrucciones para encender o apagar el LED. + +✅ Investiga: ¿Qué sucede con los mensajes MQTT si no hay un receptor? + +#### Instala Python y VS Code + +Si no tienes Python y VS Code instalados localmente, necesitarás instalarlos ambos para programar el servidor. Si estás utilizando un dispositivo IoT virtual o estás trabajando en tu Raspberry Pi, puedes omitir este paso, ya que deberías tener esto instalado y configurado. + +##### Tarea - instala Python y VS Code + +Instala Python y VS Code. + +1. Instala Python. Consulta la [página de descargas de Python](https://www.python.org/downloads/) para obtener instrucciones sobre cómo instalar la última versión de Python. + +1. Instala Visual Studio Code (VS Code). Este es el editor que usarás para escribir tu código de dispositivo virtual en Python. Consulta la [documentación de VS Code](https://code.visualstudio.com?WT.mc_id=academic-17441-jabenn) para obtener instrucciones sobre cómo instalar VS Code. +💁 Eres libre de usar cualquier IDE o editor de Python para estas lecciones si tienes una herramienta preferida, pero las lecciones darán instrucciones basadas en el uso de VS Code. +1. Instala la extensión Pylance de VS Code. Esta es una extensión para VS Code que proporciona soporte para el lenguaje Python. Consulta la [documentación de la extensión Pylance](https://marketplace.visualstudio.com/items?WT.mc_id=academic-17441-jabenn&itemName=ms-python.vscode-pylance) para obtener instrucciones sobre cómo instalar esta extensión en VS Code. + +#### Configura un entorno virtual de Python + +Una de las características más potentes de Python es la capacidad de instalar [paquetes pip](https://pypi.org), que son paquetes de código escritos por otras personas y publicados en Internet. Puedes instalar un paquete pip en tu computadora con un solo comando y luego usar ese paquete en tu código. Usarás pip para instalar un paquete que permita la comunicación a través de MQTT. + +Por defecto, cuando instalas un paquete, este está disponible en toda tu computadora, lo que puede generar problemas con las versiones de los paquetes, como que una aplicación dependa de una versión específica de un paquete que se rompe al instalar una nueva versión para otra aplicación. Para evitar este problema, puedes usar un [entorno virtual de Python](https://docs.python.org/3/library/venv.html), que es esencialmente una copia de Python en una carpeta dedicada. Cuando instalas paquetes pip, estos se instalan solo en esa carpeta. + +##### Tarea - Configura un entorno virtual de Python + +Configura un entorno virtual de Python e instala los paquetes pip para MQTT. + +1. Desde tu terminal o línea de comandos, ejecuta lo siguiente en una ubicación de tu elección para crear y navegar a un nuevo directorio: + + ```sh + mkdir nightlight-server + cd nightlight-server + ``` + +1. Ahora ejecuta lo siguiente para crear un entorno virtual en la carpeta `.venv`: + + ```sh + python3 -m venv .venv + ``` + + > 💁 Debes llamar explícitamente a `python3` para crear el entorno virtual en caso de que tengas Python 2 instalado además de Python 3 (la última versión). Si tienes Python 2 instalado, al llamar a `python` se usará Python 2 en lugar de Python 3. + +1. Activa el entorno virtual: + + * En Windows: + * Si estás usando el Command Prompt o el Command Prompt a través de Windows Terminal, ejecuta: + + ```cmd + .venv\Scripts\activate.bat + ``` + + * Si estás usando PowerShell, ejecuta: + + ```powershell + .\.venv\Scripts\Activate.ps1 + ``` + + * En macOS o Linux, ejecuta: + + ```cmd + source ./.venv/bin/activate + ``` + + > 💁 Estos comandos deben ejecutarse desde la misma ubicación donde ejecutaste el comando para crear el entorno virtual. Nunca necesitarás navegar dentro de la carpeta `.venv`; siempre debes ejecutar el comando de activación y cualquier comando para instalar paquetes o ejecutar código desde la carpeta en la que estabas cuando creaste el entorno virtual. + +1. Una vez que el entorno virtual esté activado, el comando `python` por defecto ejecutará la versión de Python que se usó para crear el entorno virtual. Ejecuta lo siguiente para obtener la versión: + + ```sh + python --version + ``` + + La salida será similar a la siguiente: + + ```output + (.venv) ➜ nightlight-server python --version + Python 3.9.1 + ``` + + > 💁 Tu versión de Python puede ser diferente; mientras sea la versión 3.6 o superior, está bien. Si no, elimina esta carpeta, instala una versión más reciente de Python e inténtalo de nuevo. + +1. Ejecuta los siguientes comandos para instalar el paquete pip para [Paho-MQTT](https://pypi.org/project/paho-mqtt/), una biblioteca popular de MQTT. + + ```sh + pip install paho-mqtt + ``` + + Este paquete pip solo se instalará en el entorno virtual y no estará disponible fuera de este. + +#### Escribe el código del servidor + +Ahora se puede escribir el código del servidor en Python. + +##### Tarea - Escribe el código del servidor + +Escribe el código del servidor. + +1. Desde tu terminal o línea de comandos, ejecuta lo siguiente dentro del entorno virtual para crear un archivo Python llamado `app.py`: + + * En Windows, ejecuta: + + ```cmd + type nul > app.py + ``` + + * En macOS o Linux, ejecuta: + + ```cmd + touch app.py + ``` + +1. Abre la carpeta actual en VS Code: + + ```sh + code . + ``` + +1. Cuando VS Code se inicie, activará el entorno virtual de Python. Esto se mostrará en la barra de estado inferior: + + ![VS Code mostrando el entorno virtual seleccionado](../../../../../translated_images/vscode-virtual-env.8ba42e04c3d533cf677e16cbe5ed9a3b80f62c6964472dc84b6f940800f0909f.es.png) + +1. Si el terminal de VS Code ya está ejecutándose cuando VS Code se inicia, no tendrá el entorno virtual activado. Lo más fácil es cerrar el terminal usando el botón **Kill the active terminal instance**: + + ![Botón de cerrar terminal activo en VS Code](../../../../../translated_images/vscode-kill-terminal.1cc4de7c6f25ee08f423f0ead714e61d069fac1eb2089e97b8a7bbcb3d45fe5e.es.png) + +1. Lanza un nuevo terminal en VS Code seleccionando *Terminal -> New Terminal*, o presionando `` CTRL+` ``. El nuevo terminal cargará el entorno virtual, con la llamada para activarlo apareciendo en el terminal. El nombre del entorno virtual (`.venv`) también estará en el prompt: + + ```output + ➜ nightlight-server source .venv/bin/activate + (.venv) ➜ nightlight + ``` + +1. Abre el archivo `app.py` desde el explorador de VS Code y agrega el siguiente código: + + ```python + import json + import time + + import paho.mqtt.client as mqtt + + id = '' + + client_telemetry_topic = id + '/telemetry' + client_name = id + 'nightlight_server' + + mqtt_client = mqtt.Client(client_name) + mqtt_client.connect('test.mosquitto.org') + + mqtt_client.loop_start() + + def handle_telemetry(client, userdata, message): + payload = json.loads(message.payload.decode()) + print("Message received:", payload) + + mqtt_client.subscribe(client_telemetry_topic) + mqtt_client.on_message = handle_telemetry + + while True: + time.sleep(2) + ``` + + Reemplaza `` en la línea 6 con el ID único que usaste al crear el código de tu dispositivo. + + ⚠️ Este **debe** ser el mismo ID que usaste en tu dispositivo, o el código del servidor no se suscribirá ni publicará en el tema correcto. + + Este código crea un cliente MQTT con un nombre único y se conecta al broker *test.mosquitto.org*. Luego inicia un bucle de procesamiento que se ejecuta en un hilo en segundo plano escuchando mensajes en cualquier tema suscrito. + + El cliente se suscribe a mensajes en el tema de telemetría y define una función que se llama cuando se recibe un mensaje. Cuando se recibe un mensaje de telemetría, se llama a la función `handle_telemetry`, que imprime el mensaje recibido en la consola. + + Finalmente, un bucle infinito mantiene la aplicación en ejecución. El cliente MQTT está escuchando mensajes en un hilo en segundo plano y funciona todo el tiempo que la aplicación principal esté en ejecución. + +1. Desde el terminal de VS Code, ejecuta lo siguiente para ejecutar tu aplicación Python: + + ```sh + python app.py + ``` + + La aplicación comenzará a escuchar mensajes del dispositivo IoT. + +1. Asegúrate de que tu dispositivo esté funcionando y enviando mensajes de telemetría. Ajusta los niveles de luz detectados por tu dispositivo físico o virtual. Los mensajes recibidos se imprimirán en el terminal. + + ```output + (.venv) ➜ nightlight-server python app.py + Message received: {'light': 0} + Message received: {'light': 400} + ``` + + El archivo `app.py` en el entorno virtual del nightlight debe estar ejecutándose para que el archivo `app.py` en el entorno virtual del nightlight-server reciba los mensajes enviados. + +> 💁 Puedes encontrar este código en la carpeta [code-server/server](../../../../../1-getting-started/lessons/4-connect-internet/code-server/server). + +### ¿Con qué frecuencia se debe enviar telemetría? + +Una consideración importante con la telemetría es con qué frecuencia medir y enviar los datos. La respuesta es: depende. Si mides con frecuencia, puedes responder más rápido a los cambios en las mediciones, pero usas más energía, más ancho de banda, generas más datos y necesitas más recursos en la nube para procesarlos. Debes medir con la frecuencia suficiente, pero no demasiado. + +Para un termostato, medir cada pocos minutos probablemente sea más que suficiente, ya que las temperaturas no cambian tan rápido. Si solo mides una vez al día, podrías terminar calentando tu casa para temperaturas nocturnas en medio de un día soleado, mientras que si mides cada segundo tendrás miles de mediciones de temperatura innecesariamente duplicadas que consumirán la velocidad y el ancho de banda de Internet del usuario (un problema para personas con planes de ancho de banda limitado), usarán más energía, lo que puede ser un problema para dispositivos alimentados por batería como sensores remotos, y aumentarán el costo de los recursos de computación en la nube del proveedor para procesarlos y almacenarlos. + +Si estás monitoreando datos de una máquina en una fábrica que, si falla, podría causar daños catastróficos y millones de dólares en pérdidas, entonces medir varias veces por segundo podría ser necesario. Es mejor desperdiciar ancho de banda que perder telemetría que indique que una máquina necesita detenerse y repararse antes de que se rompa. + +> 💁 En esta situación, podrías considerar tener un dispositivo de borde para procesar primero la telemetría y reducir la dependencia de Internet. + +### Pérdida de conectividad + +Las conexiones a Internet pueden ser poco confiables, con cortes comunes. ¿Qué debería hacer un dispositivo IoT en estas circunstancias: perder los datos o almacenarlos hasta que se restablezca la conectividad? Nuevamente, la respuesta es: depende. + +Para un termostato, los datos probablemente puedan perderse tan pronto como se tome una nueva medición de temperatura. Al sistema de calefacción no le importa que hace 20 minutos la temperatura fuera de 20.5°C si ahora es de 19°C; es la temperatura actual la que determina si la calefacción debe estar encendida o apagada. + +Para maquinaria, podrías querer conservar los datos, especialmente si se usan para buscar tendencias. Hay modelos de aprendizaje automático que pueden detectar anomalías en flujos de datos observando datos de un período de tiempo definido (como la última hora) y detectando datos anómalos. Esto se usa a menudo para mantenimiento predictivo, buscando indicios de que algo podría romperse pronto para que puedas repararlo o reemplazarlo antes de que eso ocurra. Podrías querer que se envíe cada bit de telemetría de una máquina para que pueda procesarse para la detección de anomalías, por lo que una vez que el dispositivo IoT pueda reconectarse, enviará toda la telemetría generada durante el corte de Internet. + +Los diseñadores de dispositivos IoT también deberían considerar si el dispositivo IoT puede usarse durante un corte de Internet o pérdida de señal causada por la ubicación. Un termostato inteligente debería poder tomar algunas decisiones limitadas para controlar la calefacción si no puede enviar telemetría a la nube debido a un corte. + +[![Este Ferrari quedó inutilizado porque alguien intentó actualizarlo bajo tierra donde no hay recepción celular](../../../../../translated_images/bricked-car.dc38f8efadc6c59d76211f981a521efb300939283dee468f79503aae3ec67615.es.png)](https://twitter.com/internetofshit/status/1315736960082808832) + +Para que MQTT maneje una pérdida de conectividad, el código del dispositivo y del servidor deberá ser responsable de garantizar la entrega de mensajes si es necesario, por ejemplo, exigiendo que todos los mensajes enviados sean respondidos con mensajes adicionales en un tema de respuesta, y si no lo son, se coloquen en cola manualmente para reproducirlos más tarde. + +## Comandos + +Los comandos son mensajes enviados desde la nube a un dispositivo, instruyéndolo para que haga algo. La mayoría de las veces esto implica dar algún tipo de salida a través de un actuador, pero también puede ser una instrucción para el propio dispositivo, como reiniciarse o recopilar telemetría adicional y devolverla como respuesta al comando. + +![Un termostato conectado a Internet recibiendo un comando para encender la calefacción](../../../../../translated_images/commands.d6c06bbbb3a02cce95f2831a1c331daf6dedd4e470c4aa2b0ae54f332016e504.es.png) + +Un termostato podría recibir un comando desde la nube para encender la calefacción. Basándose en los datos de telemetría de todos los sensores, si el servicio en la nube ha decidido que la calefacción debe estar encendida, enviará el comando correspondiente. + +### Enviar comandos al broker MQTT + +El siguiente paso para nuestra luz nocturna controlada por Internet es que el código del servidor envíe un comando de vuelta al dispositivo IoT para controlar la luz según los niveles de luz que detecte. + +1. Abre el código del servidor en VS Code. + +1. Agrega la siguiente línea después de la declaración de `client_telemetry_topic` para definir en qué tema enviar comandos: + + ```python + server_command_topic = id + '/commands' + ``` + +1. Agrega el siguiente código al final de la función `handle_telemetry`: + + ```python + command = { 'led_on' : payload['light'] < 300 } + print("Sending message:", command) + + client.publish(server_command_topic, json.dumps(command)) + ``` + + Esto envía un mensaje JSON al tema de comandos con el valor de `led_on` configurado en true o false dependiendo de si la luz es menor a 300 o no. Si la luz es menor a 300, se envía true para instruir al dispositivo que encienda el LED. + +1. Ejecuta el código como antes. + +1. Ajusta los niveles de luz detectados por tu dispositivo físico o virtual. Los mensajes recibidos y los comandos enviados se escribirán en el terminal: + + ```output + (.venv) ➜ nightlight-server python app.py + Message received: {'light': 0} + Sending message: {'led_on': True} + Message received: {'light': 400} + Sending message: {'led_on': False} + ``` + +> 💁 La telemetría y los comandos se están enviando en un único tema cada uno. Esto significa que la telemetría de múltiples dispositivos aparecerá en el mismo tema de telemetría, y los comandos para múltiples dispositivos aparecerán en el mismo tema de comandos. Si quisieras enviar un comando a un dispositivo específico, podrías usar múltiples temas, nombrados con un ID único de dispositivo, como `/commands/device1`, `/commands/device2`. De esa manera, un dispositivo puede escuchar mensajes destinados solo a ese dispositivo. + +> 💁 Puedes encontrar este código en la carpeta [code-commands/server](../../../../../1-getting-started/lessons/4-connect-internet/code-commands/server). + +### Manejar comandos en el dispositivo IoT + +Ahora que se están enviando comandos desde el servidor, puedes agregar código al dispositivo IoT para manejarlos y controlar el LED. + +Sigue el paso relevante a continuación para escuchar comandos desde el broker MQTT: + +* [Arduino - Wio Terminal](wio-terminal-commands.md) +* [Computadora de placa única - Raspberry Pi/Dispositivo IoT virtual](single-board-computer-commands.md) + +Una vez que este código esté escrito y en ejecución, experimenta cambiando los niveles de luz. Observa la salida del servidor y del dispositivo, y observa el LED mientras cambias los niveles de luz. + +### Pérdida de conectividad + +¿Qué debería hacer un servicio en la nube si necesita enviar un comando a un dispositivo IoT que está desconectado? Nuevamente, la respuesta es: depende. + +Si el último comando anula uno anterior, entonces probablemente se puedan ignorar los anteriores. Si un servicio en la nube envía un comando para encender la calefacción y luego envía un comando para apagarla, entonces el comando de encendido puede ignorarse y no reenviarse. + +Si los comandos necesitan procesarse en secuencia, como mover un brazo robótico hacia arriba y luego cerrar un agarrador, entonces deben enviarse en orden una vez que se restablezca la conectividad. + +✅ ¿Cómo podría el código del dispositivo o del servidor garantizar que los comandos siempre se envíen y manejen en orden a través de MQTT si es necesario? + +--- + +## 🚀 Desafío + +El desafío en las últimas tres lecciones fue listar tantos dispositivos IoT como puedas que estén en tu hogar, escuela o lugar de trabajo, y decidir si están construidos alrededor de microcontroladores o computadoras de placa única, o incluso una mezcla de ambos, y pensar en qué sensores y actuadores están utilizando. +Para estos dispositivos, piensa en qué mensajes podrían estar enviando o recibiendo. ¿Qué telemetría envían? ¿Qué mensajes o comandos podrían recibir? ¿Crees que son seguros? + +## Cuestionario posterior a la clase + +[Cuestionario posterior a la clase](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/8) + +## Revisión y estudio autónomo + +Lee más sobre MQTT en la [página de Wikipedia de MQTT](https://wikipedia.org/wiki/MQTT). + +Intenta ejecutar un broker MQTT tú mismo usando [Mosquitto](https://www.mosquitto.org) y conéctalo desde tu dispositivo IoT y código de servidor. + +> 💁 Consejo - por defecto, Mosquitto no permite conexiones anónimas (es decir, conectarse sin un nombre de usuario y contraseña), y no permite conexiones desde fuera del ordenador en el que se está ejecutando. +> Puedes solucionar esto con un [archivo de configuración `mosquitto.conf`](https://www.mosquitto.org/man/mosquitto-conf-5.html) con lo siguiente: +> +> ```sh +> listener 1883 0.0.0.0 +> allow_anonymous true +> ``` + +## Tarea + +[Compara y contrasta MQTT con otros protocolos de comunicación](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/4-connect-internet/assignment.md b/translations/es/1-getting-started/lessons/4-connect-internet/assignment.md new file mode 100644 index 00000000..b7ea8bd0 --- /dev/null +++ b/translations/es/1-getting-started/lessons/4-connect-internet/assignment.md @@ -0,0 +1,28 @@ + +# Comparar y contrastar MQTT con otros protocolos de comunicación + +## Instrucciones + +Esta lección cubrió MQTT como un protocolo de comunicación. Hay otros, incluyendo AMQP y HTTP/HTTPS. + +Investiga ambos y compáralos/contrástalos con MQTT. Piensa en el uso de energía, la seguridad y la persistencia de mensajes si se pierden las conexiones. + +## Rúbrica + +| Criterios | Ejemplar | Adecuado | Necesita Mejorar | +| --------- | --------- | -------- | ---------------- | +| Comparar AMQP con MQTT | Es capaz de comparar y contrastar AMQP con MQTT y cubre uso de energía, seguridad y persistencia de mensajes. | Es parcialmente capaz de comparar y contrastar AMQP con MQTT y cubre dos de uso de energía, seguridad y persistencia de mensajes. | Es parcialmente capaz de comparar y contrastar AMQP con MQTT y cubre uno de uso de energía, seguridad y persistencia de mensajes. | +| Comparar HTTP/HTTPS con MQTT | Es capaz de comparar y contrastar HTTP/HTTPS con MQTT y cubre uso de energía, seguridad y persistencia de mensajes. | Es parcialmente capaz de comparar y contrastar HTTP/HTTPS con MQTT y cubre dos de uso de energía, seguridad y persistencia de mensajes. | Es parcialmente capaz de comparar y contrastar HTTP/HTTPS con MQTT y cubre uno de uso de energía, seguridad y persistencia de mensajes. | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/4-connect-internet/single-board-computer-commands.md b/translations/es/1-getting-started/lessons/4-connect-internet/single-board-computer-commands.md new file mode 100644 index 00000000..5133de3f --- /dev/null +++ b/translations/es/1-getting-started/lessons/4-connect-internet/single-board-computer-commands.md @@ -0,0 +1,67 @@ + +# Controla tu luz nocturna a través de Internet - Hardware IoT Virtual y Raspberry Pi + +En esta parte de la lección, te suscribirás a los comandos enviados desde un broker MQTT a tu Raspberry Pi o dispositivo IoT virtual. + +## Suscribirse a comandos + +El siguiente paso es suscribirse a los comandos enviados desde el broker MQTT y responder a ellos. + +### Tarea + +Suscríbete a los comandos. + +1. Abre el proyecto de la luz nocturna en VS Code. + +1. Si estás utilizando un dispositivo IoT virtual, asegúrate de que la terminal esté ejecutando el entorno virtual. Si estás utilizando una Raspberry Pi, no estarás usando un entorno virtual. + +1. Agrega el siguiente código después de las definiciones de `client_telemetry_topic`: + + ```python + server_command_topic = id + '/commands' + ``` + + El `server_command_topic` es el tema MQTT al que el dispositivo se suscribirá para recibir comandos para el LED. + +1. Agrega el siguiente código justo encima del bucle principal, después de la línea `mqtt_client.loop_start()`: + + ```python + def handle_command(client, userdata, message): + payload = json.loads(message.payload.decode()) + print("Message received:", payload) + + if payload['led_on']: + led.on() + else: + led.off() + + mqtt_client.subscribe(server_command_topic) + mqtt_client.on_message = handle_command + ``` + + Este código define una función, `handle_command`, que lee un mensaje como un documento JSON y busca el valor de la propiedad `led_on`. Si está configurado en `True`, el LED se enciende; de lo contrario, se apaga. + + El cliente MQTT se suscribe al tema en el que el servidor enviará mensajes y establece la función `handle_command` para que se llame cuando se reciba un mensaje. + + > 💁 El controlador `on_message` se llama para todos los temas a los que se está suscrito. Si más adelante escribes código que escuche múltiples temas, puedes obtener el tema al que se envió el mensaje desde el objeto `message` que se pasa a la función del controlador. + +1. Ejecuta el código de la misma manera que ejecutaste el código de la parte anterior de la tarea. Si estás utilizando un dispositivo IoT virtual, asegúrate de que la aplicación CounterFit esté en ejecución y que el sensor de luz y el LED se hayan creado en los pines correctos. + +1. Ajusta los niveles de luz detectados por tu dispositivo físico o virtual. Los mensajes recibidos y los comandos enviados se escribirán en la terminal. El LED también se encenderá y apagará dependiendo del nivel de luz. + +> 💁 Puedes encontrar este código en la carpeta [code-commands/virtual-device](../../../../../1-getting-started/lessons/4-connect-internet/code-commands/virtual-device) o en la carpeta [code-commands/pi](../../../../../1-getting-started/lessons/4-connect-internet/code-commands/pi). + +😀 Has codificado con éxito tu dispositivo para responder a los comandos de un broker MQTT. + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/4-connect-internet/single-board-computer-mqtt.md b/translations/es/1-getting-started/lessons/4-connect-internet/single-board-computer-mqtt.md new file mode 100644 index 00000000..f89afdf3 --- /dev/null +++ b/translations/es/1-getting-started/lessons/4-connect-internet/single-board-computer-mqtt.md @@ -0,0 +1,93 @@ + +# Controla tu luz nocturna a través de Internet - Hardware IoT Virtual y Raspberry Pi + +El dispositivo IoT necesita ser programado para comunicarse con *test.mosquitto.org* utilizando MQTT, con el fin de enviar valores de telemetría basados en la lectura del sensor de luz y recibir comandos para controlar el LED. + +En esta parte de la lección, conectarás tu Raspberry Pi o dispositivo IoT virtual a un broker MQTT. + +## Instalar el paquete del cliente MQTT + +Para comunicarte con el broker MQTT, necesitas instalar una biblioteca MQTT como paquete de pip, ya sea en tu Raspberry Pi o en tu entorno virtual si estás utilizando un dispositivo virtual. + +### Tarea + +Instala el paquete pip + +1. Abre el proyecto de luz nocturna en VS Code. + +1. Si estás utilizando un dispositivo IoT virtual, asegúrate de que la terminal esté ejecutando el entorno virtual. Si estás utilizando una Raspberry Pi, no estarás usando un entorno virtual. + +1. Ejecuta el siguiente comando para instalar el paquete pip de MQTT: + + ```sh + pip3 install paho-mqtt + ``` + +## Programa el dispositivo + +El dispositivo está listo para ser programado. + +### Tarea + +Escribe el código del dispositivo. + +1. Agrega la siguiente importación al inicio del archivo `app.py`: + + ```python + import paho.mqtt.client as mqtt + ``` + + La biblioteca `paho.mqtt.client` permite que tu aplicación se comunique mediante MQTT. + +1. Agrega el siguiente código después de las definiciones del sensor de luz y el LED: + + ```python + id = '' + + client_name = id + 'nightlight_client' + ``` + + Reemplaza `` con un ID único que será utilizado como el nombre de este cliente del dispositivo y, más adelante, para los temas que este dispositivo publique y a los que se suscriba. El broker *test.mosquitto.org* es público y es utilizado por muchas personas, incluidos otros estudiantes que están trabajando en esta tarea. Tener un nombre único para el cliente MQTT y nombres únicos para los temas asegura que tu código no entre en conflicto con el de otros. También necesitarás este ID cuando crees el código del servidor más adelante en esta tarea. + + > 💁 Puedes usar un sitio web como [GUIDGen](https://www.guidgen.com) para generar un ID único. + + El `client_name` es un nombre único para este cliente MQTT en el broker. + +1. Agrega el siguiente código debajo de este nuevo código para crear un objeto cliente MQTT y conectarte al broker MQTT: + + ```python + mqtt_client = mqtt.Client(client_name) + mqtt_client.connect('test.mosquitto.org') + + mqtt_client.loop_start() + + print("MQTT connected!") + ``` + + Este código crea el objeto cliente, se conecta al broker MQTT público y comienza un bucle de procesamiento que se ejecuta en un hilo en segundo plano, escuchando mensajes en cualquier tema suscrito. + +1. Ejecuta el código de la misma manera que ejecutaste el código de la parte anterior de la tarea. Si estás utilizando un dispositivo IoT virtual, asegúrate de que la aplicación CounterFit esté ejecutándose y que el sensor de luz y el LED hayan sido creados en los pines correctos. + + ```output + (.venv) ➜ nightlight python app.py + MQTT connected! + Light level: 0 + Light level: 0 + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-mqtt/virtual-device](../../../../../1-getting-started/lessons/4-connect-internet/code-mqtt/virtual-device) o en la carpeta [code-mqtt/pi](../../../../../1-getting-started/lessons/4-connect-internet/code-mqtt/pi). + +😀 Has conectado exitosamente tu dispositivo a un broker MQTT. + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/4-connect-internet/single-board-computer-telemetry.md b/translations/es/1-getting-started/lessons/4-connect-internet/single-board-computer-telemetry.md new file mode 100644 index 00000000..2ee3f2a8 --- /dev/null +++ b/translations/es/1-getting-started/lessons/4-connect-internet/single-board-computer-telemetry.md @@ -0,0 +1,74 @@ + +# Controla tu luz nocturna a través de Internet - Hardware IoT Virtual y Raspberry Pi + +En esta parte de la lección, enviarás telemetría con niveles de luz desde tu Raspberry Pi o dispositivo IoT virtual a un broker MQTT. + +## Publicar telemetría + +El siguiente paso es crear un documento JSON con telemetría y enviarlo al broker MQTT. + +### Tarea + +Publica telemetría en el broker MQTT. + +1. Abre el proyecto de luz nocturna en VS Code. + +1. Si estás utilizando un dispositivo IoT virtual, asegúrate de que el terminal esté ejecutando el entorno virtual. Si estás utilizando una Raspberry Pi, no estarás usando un entorno virtual. + +1. Agrega la siguiente importación al inicio del archivo `app.py`: + + ```python + import json + ``` + + La biblioteca `json` se utiliza para codificar la telemetría como un documento JSON. + +1. Agrega lo siguiente después de la declaración de `client_name`: + + ```python + client_telemetry_topic = id + '/telemetry' + ``` + + El `client_telemetry_topic` es el tema MQTT al que el dispositivo publicará los niveles de luz. + +1. Reemplaza el contenido del bucle `while True:` al final del archivo con lo siguiente: + + ```python + while True: + light = light_sensor.light + telemetry = json.dumps({'light' : light}) + + print("Sending telemetry ", telemetry) + + mqtt_client.publish(client_telemetry_topic, telemetry) + + time.sleep(5) + ``` + + Este código empaqueta el nivel de luz en un documento JSON y lo publica en el broker MQTT. Luego, se detiene por un momento para reducir la frecuencia con la que se envían los mensajes. + +1. Ejecuta el código de la misma manera que ejecutaste el código de la parte anterior de la tarea. Si estás utilizando un dispositivo IoT virtual, asegúrate de que la aplicación CounterFit esté ejecutándose y que el sensor de luz y el LED hayan sido creados en los pines correctos. + + ```output + (.venv) ➜ nightlight python app.py + MQTT connected! + Sending telemetry {"light": 0} + Sending telemetry {"light": 0} + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-telemetry/virtual-device](../../../../../1-getting-started/lessons/4-connect-internet/code-telemetry/virtual-device) o en la carpeta [code-telemetry/pi](../../../../../1-getting-started/lessons/4-connect-internet/code-telemetry/pi). + +😀 Has enviado telemetría desde tu dispositivo con éxito. + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/4-connect-internet/wio-terminal-commands.md b/translations/es/1-getting-started/lessons/4-connect-internet/wio-terminal-commands.md new file mode 100644 index 00000000..44bbd61b --- /dev/null +++ b/translations/es/1-getting-started/lessons/4-connect-internet/wio-terminal-commands.md @@ -0,0 +1,93 @@ + +# Controla tu luz nocturna a través de Internet - Wio Terminal + +En esta parte de la lección, te suscribirás a los comandos enviados desde un broker MQTT a tu Wio Terminal. + +## Suscribirse a comandos + +El siguiente paso es suscribirse a los comandos enviados desde el broker MQTT y responder a ellos. + +### Tarea + +Suscríbete a los comandos. + +1. Abre el proyecto de luz nocturna en VS Code. + +1. Agrega el siguiente código al final del archivo `config.h` para definir el nombre del tema para los comandos: + + ```cpp + const string SERVER_COMMAND_TOPIC = ID + "/commands"; + ``` + + El `SERVER_COMMAND_TOPIC` es el tema al que el dispositivo se suscribirá para recibir comandos de LED. + +1. Agrega la siguiente línea al final de la función `reconnectMQTTClient` para suscribirte al tema de comandos cuando el cliente MQTT se reconecte: + + ```cpp + client.subscribe(SERVER_COMMAND_TOPIC.c_str()); + ``` + +1. Agrega el siguiente código debajo de la función `reconnectMQTTClient`. + + ```cpp + void clientCallback(char *topic, uint8_t *payload, unsigned int length) + { + char buff[length + 1]; + for (int i = 0; i < length; i++) + { + buff[i] = (char)payload[i]; + } + buff[length] = '\0'; + + Serial.print("Message received:"); + Serial.println(buff); + + DynamicJsonDocument doc(1024); + deserializeJson(doc, buff); + JsonObject obj = doc.as(); + + bool led_on = obj["led_on"]; + + if (led_on) + digitalWrite(D0, HIGH); + else + digitalWrite(D0, LOW); + } + ``` + + Esta función será el callback que el cliente MQTT llamará cuando reciba un mensaje del servidor. + + El mensaje se recibe como un array de enteros sin signo de 8 bits, por lo que necesita ser convertido a un array de caracteres para tratarlo como texto. + + El mensaje contiene un documento JSON, y se decodifica utilizando la biblioteca ArduinoJson. La propiedad `led_on` del documento JSON se lee, y dependiendo de su valor, el LED se enciende o se apaga. + +1. Agrega el siguiente código a la función `createMQTTClient`: + + ```cpp + client.setCallback(clientCallback); + ``` + + Este código establece el `clientCallback` como el callback que se llamará cuando se reciba un mensaje del broker MQTT. + + > 💁 El manejador `clientCallback` se llama para todos los temas suscritos. Si más adelante escribes código que escucha múltiples temas, puedes obtener el tema al que se envió el mensaje desde el parámetro `topic` que se pasa a la función callback. + +1. Sube el código a tu Wio Terminal y utiliza el Monitor Serial para ver los niveles de luz que se envían al broker MQTT. + +1. Ajusta los niveles de luz detectados por tu dispositivo físico o virtual. Verás mensajes siendo recibidos y comandos siendo enviados en el terminal. También verás el LED encendiéndose y apagándose dependiendo del nivel de luz. + +> 💁 Puedes encontrar este código en la carpeta [code-commands/wio-terminal](../../../../../1-getting-started/lessons/4-connect-internet/code-commands/wio-terminal). + +😀 Has codificado exitosamente tu dispositivo para responder a comandos de un broker MQTT. + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/4-connect-internet/wio-terminal-mqtt.md b/translations/es/1-getting-started/lessons/4-connect-internet/wio-terminal-mqtt.md new file mode 100644 index 00000000..e530da6d --- /dev/null +++ b/translations/es/1-getting-started/lessons/4-connect-internet/wio-terminal-mqtt.md @@ -0,0 +1,251 @@ + +# Controla tu luz nocturna a través de Internet - Wio Terminal + +El dispositivo IoT necesita ser programado para comunicarse con *test.mosquitto.org* utilizando MQTT, enviar valores de telemetría con la lectura del sensor de luz y recibir comandos para controlar el LED. + +En esta parte de la lección, conectarás tu Wio Terminal a un broker MQTT. + +## Instalar las bibliotecas de WiFi y MQTT para Arduino + +Para comunicarte con el broker MQTT, necesitas instalar algunas bibliotecas de Arduino para usar el chip WiFi en el Wio Terminal y comunicarte con MQTT. Al desarrollar para dispositivos Arduino, puedes usar una amplia gama de bibliotecas que contienen código de código abierto e implementan una gran variedad de funcionalidades. Seeed publica bibliotecas para el Wio Terminal que le permiten comunicarse a través de WiFi. Otros desarrolladores han publicado bibliotecas para comunicarse con brokers MQTT, y usarás estas con tu dispositivo. + +Estas bibliotecas se proporcionan como código fuente que puede ser importado automáticamente en PlatformIO y compilado para tu dispositivo. De esta manera, las bibliotecas de Arduino funcionarán en cualquier dispositivo que soporte el marco de Arduino, siempre que el dispositivo tenga el hardware específico necesario para esa biblioteca. Algunas bibliotecas, como las bibliotecas WiFi de Seeed, son específicas para ciertos hardware. + +Las bibliotecas pueden instalarse globalmente y compilarse si es necesario, o dentro de un proyecto específico. Para esta tarea, las bibliotecas se instalarán en el proyecto. + +✅ Puedes aprender más sobre la gestión de bibliotecas y cómo encontrar e instalar bibliotecas en la [documentación de bibliotecas de PlatformIO](https://docs.platformio.org/en/latest/librarymanager/index.html). + +### Tarea - instalar las bibliotecas de WiFi y MQTT para Arduino + +Instala las bibliotecas de Arduino. + +1. Abre el proyecto de luz nocturna en VS Code. + +1. Agrega lo siguiente al final del archivo `platformio.ini`: + + ```ini + lib_deps = + seeed-studio/Seeed Arduino rpcWiFi @ 1.0.5 + seeed-studio/Seeed Arduino FS @ 2.1.1 + seeed-studio/Seeed Arduino SFUD @ 2.0.2 + seeed-studio/Seeed Arduino rpcUnified @ 2.1.3 + seeed-studio/Seeed_Arduino_mbedtls @ 3.0.1 + ``` + + Esto importa las bibliotecas WiFi de Seeed. La sintaxis `@ ` se refiere a una versión específica de la biblioteca. + + > 💁 Puedes eliminar el `@ ` para usar siempre la última versión de las bibliotecas, pero no hay garantías de que las versiones posteriores funcionen con el código a continuación. El código aquí ha sido probado con esta versión de las bibliotecas. + + Esto es todo lo que necesitas hacer para agregar las bibliotecas. La próxima vez que PlatformIO compile el proyecto, descargará el código fuente de estas bibliotecas y lo compilará en tu proyecto. + +1. Agrega lo siguiente a los `lib_deps`: + + ```ini + knolleary/PubSubClient @ 2.8 + ``` + + Esto importa [PubSubClient](https://github.com/knolleary/pubsubclient), un cliente MQTT para Arduino. + +## Conectar a WiFi + +El Wio Terminal ahora puede conectarse a WiFi. + +### Tarea - conectar a WiFi + +Conecta el Wio Terminal a WiFi. + +1. Crea un nuevo archivo en la carpeta `src` llamado `config.h`. Puedes hacerlo seleccionando la carpeta `src`, o el archivo `main.cpp` dentro, y seleccionando el botón **Nuevo archivo** desde el explorador. Este botón solo aparece cuando tu cursor está sobre el explorador. + + ![El botón de nuevo archivo](../../../../../translated_images/vscode-new-file-button.182702340fe6723c8cbb4cfa1a9a9fb0d0a5227643b4e46b91ff67b07a39a92f.es.png) + +1. Agrega el siguiente código a este archivo para definir constantes con tus credenciales de WiFi: + + ```cpp + #pragma once + + #include + + using namespace std; + + // WiFi credentials + const char *SSID = ""; + const char *PASSWORD = ""; + ``` + + Reemplaza `` con el SSID de tu WiFi. Reemplaza `` con tu contraseña de WiFi. + +1. Abre el archivo `main.cpp`. + +1. Agrega las siguientes directivas `#include` al inicio del archivo: + + ```cpp + #include + #include + #include + + #include "config.h" + ``` + + Esto incluye los archivos de encabezado de las bibliotecas que agregaste anteriormente, así como el archivo de encabezado de configuración. Estos archivos de encabezado son necesarios para indicarle a PlatformIO que traiga el código de las bibliotecas. Sin incluir explícitamente estos archivos de encabezado, parte del código no se compilará y obtendrás errores de compilación. + +1. Agrega el siguiente código encima de la función `setup`: + + ```cpp + void connectWiFi() + { + while (WiFi.status() != WL_CONNECTED) + { + Serial.println("Connecting to WiFi.."); + WiFi.begin(SSID, PASSWORD); + delay(500); + } + + Serial.println("Connected!"); + } + ``` + + Este código realiza un bucle mientras el dispositivo no está conectado a WiFi e intenta conectarse utilizando el SSID y la contraseña del archivo de encabezado de configuración. + +1. Agrega una llamada a esta función al final de la función `setup`, después de que se hayan configurado los pines. + + ```cpp + connectWiFi(); + ``` + +1. Sube este código a tu dispositivo para verificar que la conexión WiFi está funcionando. Deberías ver esto en el monitor serial. + + ```output + > Executing task: platformio device monitor < + + --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time + --- More details at http://bit.ly/pio-monitor-filters + --- Miniterm on /dev/cu.usbmodem1101 9600,8,N,1 --- + --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + Connecting to WiFi.. + Connected! + ``` + +## Conectar a MQTT + +Una vez que el Wio Terminal esté conectado a WiFi, puede conectarse al broker MQTT. + +### Tarea - conectar a MQTT + +Conéctate al broker MQTT. + +1. Agrega el siguiente código al final del archivo `config.h` para definir los detalles de conexión al broker MQTT: + + ```cpp + // MQTT settings + const string ID = ""; + + const string BROKER = "test.mosquitto.org"; + const string CLIENT_NAME = ID + "nightlight_client"; + ``` + + Reemplaza `` con un ID único que se usará como el nombre del cliente de este dispositivo y más adelante para los temas que este dispositivo publique y suscriba. El broker *test.mosquitto.org* es público y es utilizado por muchas personas, incluidos otros estudiantes que están trabajando en esta tarea. Tener un nombre único para el cliente MQTT y los temas asegura que tu código no entre en conflicto con el de otros. También necesitarás este ID cuando crees el código del servidor más adelante en esta tarea. + + > 💁 Puedes usar un sitio web como [GUIDGen](https://www.guidgen.com) para generar un ID único. + + El `BROKER` es la URL del broker MQTT. + + El `CLIENT_NAME` es un nombre único para este cliente MQTT en el broker. + +1. Abre el archivo `main.cpp` y agrega el siguiente código debajo de la función `connectWiFi` y encima de la función `setup`: + + ```cpp + WiFiClient wioClient; + PubSubClient client(wioClient); + ``` + + Este código crea un cliente WiFi utilizando las bibliotecas WiFi del Wio Terminal y lo usa para crear un cliente MQTT. + +1. Debajo de este código, agrega lo siguiente: + + ```cpp + void reconnectMQTTClient() + { + while (!client.connected()) + { + Serial.print("Attempting MQTT connection..."); + + if (client.connect(CLIENT_NAME.c_str())) + { + Serial.println("connected"); + } + else + { + Serial.print("Retying in 5 seconds - failed, rc="); + Serial.println(client.state()); + + delay(5000); + } + } + } + ``` + + Esta función prueba la conexión al broker MQTT y se reconecta si no está conectado. Realiza un bucle todo el tiempo que no está conectado e intenta conectarse utilizando el nombre único del cliente definido en el archivo de encabezado de configuración. + + Si la conexión falla, vuelve a intentarlo después de 5 segundos. + +1. Agrega el siguiente código debajo de la función `reconnectMQTTClient`: + + ```cpp + void createMQTTClient() + { + client.setServer(BROKER.c_str(), 1883); + reconnectMQTTClient(); + } + ``` + + Este código configura el broker MQTT para el cliente, así como la función de callback cuando se recibe un mensaje. Luego intenta conectarse al broker. + +1. Llama a la función `createMQTTClient` en la función `setup` después de que se haya conectado a WiFi. + +1. Reemplaza toda la función `loop` con lo siguiente: + + ```cpp + void loop() + { + reconnectMQTTClient(); + client.loop(); + + delay(2000); + } + ``` + + Este código comienza reconectándose al broker MQTT. Estas conexiones pueden romperse fácilmente, por lo que vale la pena verificar regularmente y reconectar si es necesario. Luego llama al método `loop` en el cliente MQTT para procesar cualquier mensaje que esté llegando en el tema suscrito. Esta aplicación es de un solo hilo, por lo que los mensajes no pueden recibirse en un hilo de fondo; por lo tanto, se necesita tiempo en el hilo principal para procesar cualquier mensaje que esté esperando en la conexión de red. + + Finalmente, un retraso de 2 segundos asegura que los niveles de luz no se envíen con demasiada frecuencia y reduce el consumo de energía del dispositivo. + +1. Sube el código a tu Wio Terminal y usa el Monitor Serial para ver el dispositivo conectándose a WiFi y MQTT. + + ```output + > Executing task: platformio device monitor < + + source /Users/jimbennett/GitHub/IoT-For-Beginners/1-getting-started/lessons/4-connect-internet/code-mqtt/wio-terminal/nightlight/.venv/bin/activate + --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time + --- More details at http://bit.ly/pio-monitor-filters + --- Miniterm on /dev/cu.usbmodem1201 9600,8,N,1 --- + --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + Connecting to WiFi.. + Connected! + Attempting MQTT connection...connected + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-mqtt/wio-terminal](../../../../../1-getting-started/lessons/4-connect-internet/code-mqtt/wio-terminal). + +😀 Has conectado exitosamente tu dispositivo a un broker MQTT. + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/1-getting-started/lessons/4-connect-internet/wio-terminal-telemetry.md b/translations/es/1-getting-started/lessons/4-connect-internet/wio-terminal-telemetry.md new file mode 100644 index 00000000..8935dd62 --- /dev/null +++ b/translations/es/1-getting-started/lessons/4-connect-internet/wio-terminal-telemetry.md @@ -0,0 +1,93 @@ + +# Controla tu luz nocturna a través de Internet - Wio Terminal + +En esta parte de la lección, enviarás telemetría con los niveles de luz desde tu Wio Terminal al broker MQTT. + +## Instalar las bibliotecas JSON para Arduino + +Una forma popular de enviar mensajes a través de MQTT es utilizando JSON. Existe una biblioteca de Arduino para JSON que facilita la lectura y escritura de documentos JSON. + +### Tarea + +Instala la biblioteca Arduino JSON. + +1. Abre el proyecto de la luz nocturna en VS Code. + +1. Agrega la siguiente línea adicional a la lista `lib_deps` en el archivo `platformio.ini`: + + ```ini + bblanchon/ArduinoJson @ 6.17.3 + ``` + + Esto importa [ArduinoJson](https://arduinojson.org), una biblioteca JSON para Arduino. + +## Publicar telemetría + +El siguiente paso es crear un documento JSON con la telemetría y enviarlo al broker MQTT. + +### Tarea - publicar telemetría + +Publica telemetría en el broker MQTT. + +1. Agrega el siguiente código al final del archivo `config.h` para definir el nombre del tema de telemetría para el broker MQTT: + + ```cpp + const string CLIENT_TELEMETRY_TOPIC = ID + "/telemetry"; + ``` + + El `CLIENT_TELEMETRY_TOPIC` es el tema al que el dispositivo publicará los niveles de luz. + +1. Abre el archivo `main.cpp`. + +1. Agrega la siguiente directiva `#include` al principio del archivo: + + ```cpp + #include + ``` + +1. Agrega el siguiente código dentro de la función `loop`, justo antes del `delay`: + + ```cpp + int light = analogRead(WIO_LIGHT); + + DynamicJsonDocument doc(1024); + doc["light"] = light; + + string telemetry; + serializeJson(doc, telemetry); + + Serial.print("Sending telemetry "); + Serial.println(telemetry.c_str()); + + client.publish(CLIENT_TELEMETRY_TOPIC.c_str(), telemetry.c_str()); + ``` + + Este código lee el nivel de luz y crea un documento JSON utilizando ArduinoJson que contiene este nivel. Luego, se serializa a una cadena y se publica en el tema de telemetría MQTT mediante el cliente MQTT. + +1. Sube el código a tu Wio Terminal y utiliza el Monitor Serial para ver los niveles de luz que se envían al broker MQTT. + + ```output + Connecting to WiFi.. + Connected! + Attempting MQTT connection...connected + Sending telemetry {"light":652} + Sending telemetry {"light":612} + Sending telemetry {"light":583} + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-telemetry/wio-terminal](../../../../../1-getting-started/lessons/4-connect-internet/code-telemetry/wio-terminal). + +😀 Has enviado telemetría desde tu dispositivo con éxito. + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/README.md b/translations/es/2-farm/README.md new file mode 100644 index 00000000..55a55d2c --- /dev/null +++ b/translations/es/2-farm/README.md @@ -0,0 +1,34 @@ + +# Agricultura con IoT + +A medida que la población crece, también lo hace la demanda en la agricultura. La cantidad de tierra disponible no cambia, pero el clima sí, lo que plantea aún más desafíos para los agricultores, especialmente los 2 mil millones de [agricultores de subsistencia](https://wikipedia.org/wiki/Subsistence_agriculture) que dependen de lo que cultivan para poder comer y alimentar a sus familias. El IoT puede ayudar a los agricultores a tomar decisiones más inteligentes sobre qué cultivar y cuándo cosechar, aumentar los rendimientos, reducir la cantidad de trabajo manual y detectar y tratar las plagas. + +En estas 6 lecciones aprenderás cómo aplicar el Internet de las Cosas para mejorar y automatizar la agricultura. + +> 💁 Estas lecciones utilizarán algunos recursos en la nube. Si no completas todas las lecciones de este proyecto, asegúrate de [limpiar tu proyecto](../clean-up.md). + +## Temas + +1. [Predecir el crecimiento de las plantas con IoT](lessons/1-predict-plant-growth/README.md) +1. [Detectar la humedad del suelo](lessons/2-detect-soil-moisture/README.md) +1. [Riego automatizado de plantas](lessons/3-automated-plant-watering/README.md) +1. [Migrar tu planta a la nube](lessons/4-migrate-your-plant-to-the-cloud/README.md) +1. [Migrar la lógica de tu aplicación a la nube](lessons/5-migrate-application-to-the-cloud/README.md) +1. [Mantén tu planta segura](lessons/6-keep-your-plant-secure/README.md) + +## Créditos + +Todas las lecciones fueron escritas con ♥️ por [Jim Bennett](https://GitHub.com/JimBobBennett) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/1-predict-plant-growth/README.md b/translations/es/2-farm/lessons/1-predict-plant-growth/README.md new file mode 100644 index 00000000..eca1bd3e --- /dev/null +++ b/translations/es/2-farm/lessons/1-predict-plant-growth/README.md @@ -0,0 +1,278 @@ + +## Pre-lecture quiz + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/9) + +## Introducción + +Las plantas necesitan ciertos elementos para crecer: agua, dióxido de carbono, nutrientes, luz y calor. En esta lección, aprenderás cómo calcular las tasas de crecimiento y madurez de las plantas midiendo la temperatura del aire. + +En esta lección cubriremos: + +* [Agricultura digital](../../../../../2-farm/lessons/1-predict-plant-growth) +* [¿Por qué es importante la temperatura en la agricultura?](../../../../../2-farm/lessons/1-predict-plant-growth) +* [Medir la temperatura ambiente](../../../../../2-farm/lessons/1-predict-plant-growth) +* [Días grado de crecimiento (GDD)](../../../../../2-farm/lessons/1-predict-plant-growth) +* [Calcular GDD usando datos de sensores de temperatura](../../../../../2-farm/lessons/1-predict-plant-growth) + +## Agricultura digital + +La agricultura digital está transformando la forma en que cultivamos, utilizando herramientas para recopilar, almacenar y analizar datos agrícolas. Actualmente estamos en un período descrito como la 'Cuarta Revolución Industrial' por el Foro Económico Mundial, y el auge de la agricultura digital ha sido denominado la 'Cuarta Revolución Agrícola' o 'Agricultura 4.0'. + +> 🎓 El término Agricultura Digital también incluye toda la 'cadena de valor agrícola', es decir, todo el recorrido desde la granja hasta la mesa. Incluye el seguimiento de la calidad de los productos mientras se transportan y procesan, sistemas de almacén y comercio electrónico, e incluso aplicaciones para alquilar tractores. + +Estos cambios permiten a los agricultores aumentar los rendimientos, usar menos fertilizantes y pesticidas, y optimizar el uso del agua. Aunque principalmente se utiliza en países más ricos, los sensores y otros dispositivos están reduciendo lentamente su precio, haciéndolos más accesibles en países en desarrollo. + +Algunas técnicas habilitadas por la agricultura digital son: + +* Medición de temperatura: medir la temperatura permite a los agricultores predecir el crecimiento y la madurez de las plantas. +* Riego automatizado: medir la humedad del suelo y activar los sistemas de riego cuando el suelo está demasiado seco, en lugar de regar según un horario. El riego programado puede llevar a que los cultivos reciban poca agua durante una ola de calor y sequía, o demasiada agua durante la lluvia. Al regar solo cuando el suelo lo necesita, los agricultores pueden optimizar el uso del agua. +* Control de plagas: los agricultores pueden usar cámaras en robots automatizados o drones para buscar plagas y luego aplicar pesticidas solo donde sea necesario, reduciendo la cantidad de pesticidas utilizados y minimizando el impacto en los suministros de agua locales. + +✅ Investiga. ¿Qué otras técnicas se utilizan para mejorar los rendimientos agrícolas? + +> 🎓 El término 'Agricultura de Precisión' se utiliza para definir la observación, medición y respuesta a los cultivos en función de cada campo, o incluso de partes de un campo. Esto incluye medir niveles de agua, nutrientes y plagas y responder con precisión, como regar solo una pequeña parte de un campo. + +## ¿Por qué es importante la temperatura en la agricultura? + +Cuando aprendemos sobre las plantas, la mayoría de los estudiantes son enseñados sobre la necesidad de agua, luz, dióxido de carbono y nutrientes. Las plantas también necesitan calor para crecer; por eso florecen en primavera cuando la temperatura aumenta, por qué los narcisos o campanillas pueden brotar temprano debido a un breve período cálido, y por qué los invernaderos son tan efectivos para hacer crecer las plantas. + +> 🎓 Los invernaderos y los hothouses hacen un trabajo similar, pero con una diferencia importante. Los hothouses se calientan artificialmente y permiten a los agricultores controlar las temperaturas con mayor precisión, mientras que los invernaderos dependen del sol para el calor y generalmente solo tienen ventanas u otras aperturas para dejar salir el calor. + +Las plantas tienen una temperatura base o mínima, una temperatura óptima y una temperatura máxima, todas basadas en temperaturas promedio diarias. + +* Temperatura base: es la temperatura promedio diaria mínima necesaria para que una planta crezca. +* Temperatura óptima: es la mejor temperatura promedio diaria para obtener el mayor crecimiento. +* Temperatura máxima: es la temperatura máxima que una planta puede soportar. Por encima de esta, la planta detendrá su crecimiento para conservar agua y sobrevivir. + +> 💁 Estas son temperaturas promedio, calculadas a partir de las temperaturas diurnas y nocturnas. Las plantas también necesitan diferentes temperaturas durante el día y la noche para fotosintetizar de manera más eficiente y ahorrar energía por la noche. + +Cada especie de planta tiene valores diferentes para su temperatura base, óptima y máxima. Por eso algunas plantas prosperan en países cálidos y otras en países fríos. + +✅ Investiga. Para las plantas que tengas en tu jardín, escuela o parque local, ¿puedes encontrar la temperatura base? + +![Un gráfico que muestra la tasa de crecimiento aumentando a medida que la temperatura sube, y luego disminuyendo cuando la temperatura es demasiado alta](../../../../../translated_images/plant-growth-temp-graph.c6d69c9478e6ca832baa8dcb8d4adcbb67304074ce50e94ac8faae95975177f9.es.png) + +El gráfico anterior muestra un ejemplo de la relación entre la tasa de crecimiento y la temperatura. Hasta la temperatura base no hay crecimiento. La tasa de crecimiento aumenta hasta la temperatura óptima y luego disminuye después de alcanzar este pico. A la temperatura máxima, el crecimiento se detiene. + +La forma de este gráfico varía según la especie de planta. Algunas tienen caídas más pronunciadas por encima de la temperatura óptima, otras tienen aumentos más lentos desde la base hasta la óptima. + +> 💁 Para que un agricultor obtenga el mejor crecimiento, necesitará conocer los tres valores de temperatura y entender la forma de los gráficos para las plantas que está cultivando. + +Si un agricultor tiene control de la temperatura, por ejemplo, en un hothouse comercial, entonces puede optimizar para sus plantas. Un hothouse comercial que cultiva tomates, por ejemplo, tendrá la temperatura configurada alrededor de 25°C durante el día y 20°C por la noche para obtener el crecimiento más rápido. + +> 🍅 Combinando estas temperaturas con luces artificiales, fertilizantes y niveles controlados de dióxido de carbono, los productores comerciales pueden cultivar y cosechar durante todo el año. + +## Medir la temperatura ambiente + +Los sensores de temperatura pueden usarse con dispositivos IoT para medir la temperatura ambiente. + +### Tarea - medir la temperatura + +Sigue la guía correspondiente para monitorear temperaturas usando tu dispositivo IoT: + +* [Arduino - Wio Terminal](wio-terminal-temp.md) +* [Computadora de placa única - Raspberry Pi](pi-temp.md) +* [Computadora de placa única - Dispositivo virtual](virtual-device-temp.md) + +## Días grado de crecimiento + +Los días grado de crecimiento (también conocidos como unidades grado de crecimiento) son una forma de medir el crecimiento de las plantas en función de la temperatura. Suponiendo que una planta tiene suficiente agua, nutrientes y dióxido de carbono, la temperatura determina la tasa de crecimiento. + +Los días grado de crecimiento, o GDD, se calculan por día como la temperatura promedio en Celsius de un día por encima de la temperatura base de la planta. Cada planta necesita un cierto número de GDD para crecer, florecer o producir y madurar un cultivo. Cuantos más GDD por día, más rápido crecerá la planta. + +> 🇺🇸 Para los estadounidenses, los días grado de crecimiento también pueden calcularse usando Fahrenheit. 5 GDD (en Celsius) equivalen a 9 GDD (en Fahrenheit). + +La fórmula completa para calcular GDD es un poco complicada, pero hay una ecuación simplificada que a menudo se utiliza como una buena aproximación: + +![GDD = T max + T min dividido por 2, todo menos T base](../../../../../translated_images/gdd-calculation.79b3660f9c5757aa92dc2dd2cdde75344e2d2c1565c4b3151640f7887edc0275.es.png) + +* **GDD** - este es el número de días grado de crecimiento +* **T max** - esta es la temperatura máxima diaria en grados Celsius +* **T min** - esta es la temperatura mínima diaria en grados Celsius +* **T base** - esta es la temperatura base de la planta en grados Celsius + +> 💁 Hay variaciones que consideran T max por encima de 30°C o T min por debajo de T base, pero las ignoraremos por ahora. + +### Ejemplo - Maíz 🌽 + +Dependiendo de la variedad, el maíz necesita entre 800 y 2,700 GDD para madurar, con una temperatura base de 10°C. + +En el primer día por encima de la temperatura base, se midieron las siguientes temperaturas: + +| Medición | Temp °C | +| :---------- | :-----: | +| Máxima | 16 | +| Mínima | 12 | + +Usando estos números en nuestra fórmula: + +* T max = 16 +* T min = 12 +* T base = 10 + +Esto da un cálculo de: + +![GDD = 16 + 12 dividido por 2, todo menos 10, dando un resultado de 4](../../../../../translated_images/gdd-calculation-corn.64a58b7a7afcd0dfd46ff733996d939f17f4f3feac9f0d1c632be3523e51ebd9.es.png) + +El maíz recibió 4 GDD ese día. Suponiendo una variedad de maíz que necesita 800 GDD para madurar, necesitará otros 796 GDD para alcanzar la madurez. + +✅ Investiga. Para las plantas que tengas en tu jardín, escuela o parque local, ¿puedes encontrar el número de GDD necesarios para alcanzar la madurez o producir cultivos? + +## Calcular GDD usando datos de sensores de temperatura + +Las plantas no crecen en fechas fijas; por ejemplo, no puedes plantar una semilla y saber que la planta dará frutos exactamente 100 días después. En cambio, como agricultor puedes tener una idea aproximada de cuánto tiempo tarda una planta en crecer y luego verificar diariamente para ver cuándo los cultivos están listos. + +Esto tiene un gran impacto en la mano de obra en una granja y corre el riesgo de que el agricultor pase por alto cultivos que estén listos inesperadamente temprano. Al medir las temperaturas, el agricultor puede calcular los GDD que una planta ha recibido, permitiéndole verificar solo cerca de la madurez esperada. + +Al recopilar datos de temperatura usando un dispositivo IoT, un agricultor puede ser notificado automáticamente cuando las plantas están cerca de la madurez. Una arquitectura típica para esto es que los dispositivos IoT midan la temperatura y luego publiquen estos datos de telemetría a través de Internet usando algo como MQTT. El código del servidor escucha estos datos y los guarda en algún lugar, como en una base de datos. Esto significa que los datos pueden analizarse más tarde, como un trabajo nocturno para calcular los GDD del día, sumar los GDD totales para cada cultivo hasta ahora y alertar si una planta está cerca de la madurez. + +![Los datos de telemetría se envían a un servidor y luego se guardan en una base de datos](../../../../../translated_images/save-telemetry-database.ddc9c6bea0c5ba39449966a463ca6748cd8e2d565dab44ff31c9f1d2f6c21d27.es.png) + +El código del servidor también puede complementar los datos agregando información adicional. Por ejemplo, el dispositivo IoT puede publicar un identificador para indicar qué dispositivo es, y el código del servidor puede usar esto para buscar la ubicación del dispositivo y qué cultivos está monitoreando. También puede agregar datos básicos como la hora actual, ya que algunos dispositivos IoT no tienen el hardware necesario para llevar un registro preciso del tiempo o requieren código adicional para leer la hora actual a través de Internet. + +✅ ¿Por qué crees que diferentes campos pueden tener diferentes temperaturas? + +### Tarea - publicar información de temperatura + +Sigue la guía correspondiente para publicar datos de temperatura a través de MQTT usando tu dispositivo IoT para que puedan analizarse más tarde: + +* [Arduino - Wio Terminal](wio-terminal-temp-publish.md) +* [Computadora de placa única - Raspberry Pi/Dispositivo IoT virtual](single-board-computer-temp-publish.md) + +### Tarea - capturar y almacenar la información de temperatura + +Una vez que el dispositivo IoT esté publicando telemetría, se puede escribir el código del servidor para suscribirse a estos datos y almacenarlos. En lugar de guardarlos en una base de datos, el código del servidor los guardará en un archivo de valores separados por comas (CSV). Los archivos CSV almacenan datos como filas de valores en texto, con cada valor separado por una coma y cada registro en una nueva línea. Son una forma conveniente, legible y ampliamente compatible de guardar datos como archivo. + +El archivo CSV tendrá dos columnas: *fecha* y *temperatura*. La columna *fecha* se establece como la fecha y hora actuales en que el mensaje fue recibido por el servidor, y la *temperatura* proviene del mensaje de telemetría. + +1. Repite los pasos de la lección 4 para crear el código del servidor que se suscriba a la telemetría. No necesitas agregar código para publicar comandos. + + Los pasos para esto son: + + * Configurar y activar un entorno virtual de Python + + * Instalar el paquete pip paho-mqtt + + * Escribir el código para escuchar mensajes MQTT publicados en el tema de telemetría + + > ⚠️ Puedes consultar [las instrucciones en la lección 4 para crear una aplicación Python que reciba telemetría si es necesario](../../../1-getting-started/lessons/4-connect-internet/README.md#receive-telemetry-from-the-mqtt-broker). + + Nombra la carpeta para este proyecto `temperature-sensor-server`. + +1. Asegúrate de que el `client_name` refleje este proyecto: + + ```cpp + client_name = id + 'temperature_sensor_server' + ``` + +1. Agrega las siguientes importaciones al inicio del archivo, debajo de las importaciones existentes: + + ```python + from os import path + import csv + from datetime import datetime + ``` + + Esto importa una biblioteca para leer archivos, una biblioteca para interactuar con archivos CSV y una biblioteca para trabajar con fechas y horas. + +1. Agrega el siguiente código antes de la función `handle_telemetry`: + + ```python + temperature_file_name = 'temperature.csv' + fieldnames = ['date', 'temperature'] + + if not path.exists(temperature_file_name): + with open(temperature_file_name, mode='w') as csv_file: + writer = csv.DictWriter(csv_file, fieldnames=fieldnames) + writer.writeheader() + ``` + + Este código declara algunas constantes para el nombre del archivo donde se escribirá y los nombres de las columnas del archivo CSV. La primera fila de un archivo CSV tradicionalmente contiene encabezados de columna separados por comas. + + Luego, el código verifica si el archivo CSV ya existe. Si no existe, se crea con los encabezados de columna en la primera fila. + +1. Agrega el siguiente código al final de la función `handle_telemetry`: + + ```python + with open(temperature_file_name, mode='a') as temperature_file: + temperature_writer = csv.DictWriter(temperature_file, fieldnames=fieldnames) + temperature_writer.writerow({'date' : datetime.now().astimezone().replace(microsecond=0).isoformat(), 'temperature' : payload['temperature']}) + ``` +Este código abre el archivo CSV y luego agrega una nueva fila al final. La fila contiene la fecha y hora actual formateadas en un formato legible para humanos, seguido de la temperatura recibida del dispositivo IoT. Los datos se almacenan en [formato ISO 8601](https://wikipedia.org/wiki/ISO_8601) con la zona horaria, pero sin microsegundos. + +1. Ejecuta este código de la misma manera que antes, asegurándote de que tu dispositivo IoT esté enviando datos. Se creará un archivo CSV llamado `temperature.csv` en la misma carpeta. Si lo abres, verás fechas/horas y mediciones de temperatura: + + ```output + date,temperature + 2021-04-19T17:21:36-07:00,25 + 2021-04-19T17:31:36-07:00,24 + 2021-04-19T17:41:36-07:00,25 + ``` + +1. Ejecuta este código durante un tiempo para capturar datos. Idealmente, deberías ejecutarlo durante todo un día para recopilar suficientes datos para los cálculos de GDD. + + +> 💁 Si estás utilizando un dispositivo IoT virtual, selecciona la casilla de aleatoriedad y establece un rango para evitar obtener la misma temperatura cada vez que se devuelva el valor de temperatura. + ![Selecciona la casilla de aleatoriedad y establece un rango](../../../../../translated_images/select-the-random-checkbox-and-set-a-range.32cf4bc7c12e797f8c76616b10c7c23a6592321bb1a6310e0b481e72f97d23b3.es.png) + + > 💁 Si deseas ejecutarlo durante todo un día, debes asegurarte de que la computadora donde se ejecuta tu código de servidor no entre en modo de suspensión, ya sea cambiando la configuración de energía o ejecutando algo como [este script de Python para mantener el sistema activo](https://github.com/jaqsparow/keep-system-active). + +> 💁 Puedes encontrar este código en la carpeta [code-server/temperature-sensor-server](../../../../../2-farm/lessons/1-predict-plant-growth/code-server/temperature-sensor-server). + +### Tarea - calcular GDD usando los datos almacenados + +Una vez que el servidor haya capturado los datos de temperatura, se puede calcular el GDD para una planta. + +Los pasos para hacerlo manualmente son: + +1. Encuentra la temperatura base para la planta. Por ejemplo, para las fresas la temperatura base es de 10°C. + +1. En el archivo `temperature.csv`, encuentra las temperaturas más altas y más bajas del día. + +1. Usa el cálculo de GDD dado anteriormente para calcular el GDD. + +Por ejemplo, si la temperatura más alta del día es 25°C y la más baja es 12°C: + +![GDD = 25 + 12 dividido por 2, luego resta 10 del resultado dando 8.5](../../../../../translated_images/gdd-calculation-strawberries.59f57db94b22adb8ff6efb951ace33af104a1c6ccca3ffb0f8169c14cb160c90.es.png) + +* 25 + 12 = 37 +* 37 / 2 = 18.5 +* 18.5 - 10 = 8.5 + +Por lo tanto, las fresas han recibido **8.5** GDD. Las fresas necesitan alrededor de 250 GDD para dar fruto, así que aún falta un tiempo. + +--- + +## 🚀 Desafío + +Las plantas necesitan más que calor para crecer. ¿Qué otras cosas son necesarias? + +Para estas, investiga si hay sensores que puedan medirlas. ¿Qué hay de los actuadores para controlar estos niveles? ¿Cómo podrías ensamblar uno o más dispositivos IoT para optimizar el crecimiento de las plantas? + +## Cuestionario posterior a la clase + +[Cuestionario posterior a la clase](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/10) + +## Revisión y autoestudio + +* Lee más sobre agricultura digital en la [página de Wikipedia sobre Agricultura Digital](https://wikipedia.org/wiki/Digital_agriculture). También lee más sobre agricultura de precisión en la [página de Wikipedia sobre Agricultura de Precisión](https://wikipedia.org/wiki/Precision_agriculture). +* El cálculo completo de los grados día de crecimiento es más complicado que el simplificado dado aquí. Lee más sobre la ecuación más compleja y cómo manejar temperaturas por debajo del umbral en la [página de Wikipedia sobre Grados Día de Crecimiento](https://wikipedia.org/wiki/Growing_degree-day). +* Los alimentos podrían escasear en el futuro si seguimos utilizando los mismos métodos de cultivo. Aprende más sobre técnicas de agricultura de alta tecnología en este [video sobre Granjas de Alta Tecnología del Futuro en YouTube](https://www.youtube.com/watch?v=KIEOuKD9KX8). + +## Asignación + +[Visualiza los datos de GDD usando un Jupyter Notebook](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de ningún malentendido o interpretación errónea que surja del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/1-predict-plant-growth/assignment.md b/translations/es/2-farm/lessons/1-predict-plant-growth/assignment.md new file mode 100644 index 00000000..13a57b5d --- /dev/null +++ b/translations/es/2-farm/lessons/1-predict-plant-growth/assignment.md @@ -0,0 +1,57 @@ + +# Visualizar datos de GDD usando un Jupyter Notebook + +## Instrucciones + +En esta lección recopilaste datos de GDD utilizando un sensor IoT. Para obtener buenos datos de GDD, necesitas recopilar datos durante varios días. Para ayudar a visualizar los datos de temperatura y calcular el GDD, puedes usar herramientas como [Jupyter Notebooks](https://jupyter.org) para analizar los datos. + +Comienza recopilando datos durante algunos días. Deberás asegurarte de que el código de tu servidor esté funcionando todo el tiempo que tu dispositivo IoT esté activo, ya sea ajustando la configuración de administración de energía o ejecutando algo como [este script de Python para mantener el sistema activo](https://github.com/jaqsparow/keep-system-active). + +Una vez que tengas los datos de temperatura, puedes usar el Jupyter Notebook en este repositorio para visualizarlos y calcular el GDD. Los Jupyter Notebooks combinan código e instrucciones en bloques llamados *celdas*, a menudo con código en Python. Puedes leer las instrucciones y luego ejecutar cada bloque de código, uno por uno. También puedes editar el código. En este notebook, por ejemplo, puedes editar la temperatura base utilizada para calcular el GDD de tu planta. + +1. Crea una carpeta llamada `gdd-calculation` + +1. Descarga el archivo [gdd.ipynb](./code-notebook/gdd.ipynb) y cópialo en la carpeta `gdd-calculation`. + +1. Copia el archivo `temperature.csv` creado por el servidor MQTT. + +1. Crea un nuevo entorno virtual de Python en la carpeta `gdd-calculation`. + +1. Instala algunos paquetes de pip para Jupyter Notebooks, junto con las bibliotecas necesarias para gestionar y graficar los datos: + + ```sh + pip install --upgrade pip + pip install pandas + pip install matplotlib + pip install jupyter + ``` + +1. Ejecuta el notebook en Jupyter: + + ```sh + jupyter notebook gdd.ipynb + ``` + + Jupyter se iniciará y abrirá el notebook en tu navegador. Sigue las instrucciones en el notebook para visualizar las temperaturas medidas y calcular los días grado de crecimiento. + + ![El jupyter notebook](../../../../../translated_images/gdd-jupyter-notebook.c5b52cf21094f158a61f47f455490fd95f1729777ff90861a4521820bf354cdc.es.png) + +## Rúbrica + +| Criterios | Ejemplar | Adecuado | Necesita Mejorar | +| --------- | -------- | -------- | ---------------- | +| Captura de datos | Captura al menos 2 días completos de datos | Captura al menos 1 día completo de datos | Captura algunos datos | +| Cálculo de GDD | Ejecuta exitosamente el notebook y calcula el GDD | Ejecuta exitosamente el notebook | No logra ejecutar el notebook | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/1-predict-plant-growth/code-notebook/gdd.ipynb b/translations/es/2-farm/lessons/1-predict-plant-growth/code-notebook/gdd.ipynb new file mode 100644 index 00000000..6c7bf353 --- /dev/null +++ b/translations/es/2-farm/lessons/1-predict-plant-growth/code-notebook/gdd.ipynb @@ -0,0 +1,167 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Días Grado de Crecimiento\n", + "\n", + "Este cuaderno carga datos de temperatura guardados en un archivo CSV y los analiza. Traza las temperaturas, muestra el valor más alto y más bajo de cada día, y calcula los GDD.\n", + "\n", + "Para usar este cuaderno:\n", + "\n", + "* Copia el archivo `temperature.csv` en la misma carpeta que este cuaderno.\n", + "* Ejecuta todas las celdas usando el botón **▶︎ Run** de arriba. Esto ejecutará la celda seleccionada y luego pasará a la siguiente.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "En la celda de abajo, establece `base_temperature` a la temperatura base de la planta.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "base_temperature = 10" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "El archivo CSV ahora necesita ser cargado, usando pandas\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Read the temperature CSV file\n", + "df = pd.read_csv('temperature.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure(figsize=(20, 10))\n", + "plt.plot(df['date'], df['temperature'])\n", + "plt.xticks(rotation='vertical');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Una vez que se hayan leído los datos, se pueden agrupar por la columna `date`, y se pueden extraer las temperaturas mínimas y máximas para cada fecha.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Convert datetimes to pure dates so we can group by the date\n", + "df['date'] = pd.to_datetime(df['date']).dt.date\n", + "\n", + "# Group the data by date so it can be analyzed by date\n", + "data_by_date = df.groupby('date')\n", + "\n", + "# Get the minimum and maximum temperatures for each date\n", + "min_by_date = data_by_date.min()\n", + "max_by_date = data_by_date.max()\n", + "\n", + "# Join the min and max temperatures into one dataframe and flatten it\n", + "min_max_by_date = min_by_date.join(max_by_date, on='date', lsuffix='_min', rsuffix='_max')\n", + "min_max_by_date = min_max_by_date.reset_index()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "La GDD se puede calcular utilizando la ecuación estándar de GDD\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_gdd(row):\n", + " return ((row['temperature_max'] + row['temperature_min']) / 2) - base_temperature\n", + "\n", + "# Calculate the GDD for each row\n", + "min_max_by_date['gdd'] = min_max_by_date.apply (lambda row: calculate_gdd(row), axis=1)\n", + "\n", + "# Print the results\n", + "print(min_max_by_date[['date', 'gdd']].to_string(index=False))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n---\n\n**Descargo de responsabilidad**: \nEste documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.1" + }, + "metadata": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + }, + "coopTranslator": { + "original_hash": "8fcf954f6042f0bf3601a2c836a09574", + "translation_date": "2025-08-26T15:59:36+00:00", + "source_file": "2-farm/lessons/1-predict-plant-growth/code-notebook/gdd.ipynb", + "language_code": "es" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/translations/es/2-farm/lessons/1-predict-plant-growth/pi-temp.md b/translations/es/2-farm/lessons/1-predict-plant-growth/pi-temp.md new file mode 100644 index 00000000..89911eb3 --- /dev/null +++ b/translations/es/2-farm/lessons/1-predict-plant-growth/pi-temp.md @@ -0,0 +1,125 @@ + +# Medir la temperatura - Raspberry Pi + +En esta parte de la lección, agregarás un sensor de temperatura a tu Raspberry Pi. + +## Hardware + +El sensor que usarás es un [sensor de humedad y temperatura DHT11](https://www.seeedstudio.com/Grove-Temperature-Humidity-Sensor-DHT11.html), que combina 2 sensores en un solo paquete. Este sensor es bastante popular, con varios modelos comerciales que combinan temperatura, humedad y, a veces, presión atmosférica. El componente del sensor de temperatura es un termistor de coeficiente de temperatura negativo (NTC), un tipo de termistor cuya resistencia disminuye a medida que aumenta la temperatura. + +Este es un sensor digital, por lo que tiene un ADC integrado que genera una señal digital con los datos de temperatura y humedad que el microcontrolador puede leer. + +### Conectar el sensor de temperatura + +El sensor de temperatura Grove se puede conectar a la Raspberry Pi. + +#### Tarea + +Conecta el sensor de temperatura. + +![Un sensor de temperatura Grove](../../../../../translated_images/grove-dht11.07f8eafceee170043efbb53e1d15722bd4e00fbaa9ff74290b57e9f66eb82c17.es.png) + +1. Inserta un extremo de un cable Grove en el conector del sensor de humedad y temperatura. Solo encajará de una manera. + +1. Con la Raspberry Pi apagada, conecta el otro extremo del cable Grove al conector digital marcado como **D5** en el Grove Base Hat conectado a la Pi. Este conector es el segundo desde la izquierda, en la fila de conectores junto a los pines GPIO. + +![El sensor de temperatura Grove conectado al conector A0](../../../../../translated_images/pi-temperature-sensor.3ff82fff672c8e565ef25a39d26d111de006b825a7e0867227ef4e7fbff8553c.es.png) + +## Programar el sensor de temperatura + +Ahora se puede programar el dispositivo para usar el sensor de temperatura conectado. + +### Tarea + +Programa el dispositivo. + +1. Enciende la Raspberry Pi y espera a que inicie. + +1. Abre VS Code, ya sea directamente en la Pi o conectándote a través de la extensión Remote SSH. + + > ⚠️ Puedes consultar [las instrucciones para configurar y abrir VS Code en la lección 1 si es necesario](../../../1-getting-started/lessons/1-introduction-to-iot/pi.md). + +1. Desde el terminal, crea una nueva carpeta en el directorio de inicio del usuario `pi` llamada `temperature-sensor`. Crea un archivo en esta carpeta llamado `app.py`: + + ```sh + mkdir temperature-sensor + cd temperature-sensor + touch app.py + ``` + +1. Abre esta carpeta en VS Code. + +1. Para usar el sensor de temperatura y humedad, es necesario instalar un paquete adicional de Pip. Desde el terminal en VS Code, ejecuta el siguiente comando para instalar este paquete en la Pi: + + ```sh + pip3 install seeed-python-dht + ``` + +1. Agrega el siguiente código al archivo `app.py` para importar las bibliotecas necesarias: + + ```python + import time + from seeed_dht import DHT + ``` + + La instrucción `from seeed_dht import DHT` importa la clase `DHT` para interactuar con un sensor de temperatura Grove desde el módulo `seeed_dht`. + +1. Agrega el siguiente código después del anterior para crear una instancia de la clase que gestiona el sensor de temperatura: + + ```python + sensor = DHT("11", 5) + ``` + + Esto declara una instancia de la clase `DHT` que gestiona el sensor de **H**umedad y **T**emperatura **D**igital. El primer parámetro indica que el sensor utilizado es el *DHT11* (la biblioteca que estás usando admite otras variantes de este sensor). El segundo parámetro indica que el sensor está conectado al puerto digital `D5` en el Grove Base Hat. + + > ✅ Recuerda, todos los conectores tienen números de pines únicos. Los pines 0, 2, 4 y 6 son pines analógicos, mientras que los pines 5, 16, 18, 22, 24 y 26 son pines digitales. + +1. Agrega un bucle infinito después del código anterior para consultar el valor del sensor de temperatura y mostrarlo en la consola: + + ```python + while True: + _, temp = sensor.read() + print(f'Temperature {temp}°C') + ``` + + La llamada a `sensor.read()` devuelve una tupla con la humedad y la temperatura. Solo necesitas el valor de la temperatura, por lo que se ignora la humedad. El valor de la temperatura se imprime en la consola. + +1. Agrega una pequeña pausa de diez segundos al final del `loop`, ya que no es necesario verificar los niveles de temperatura continuamente. Una pausa reduce el consumo de energía del dispositivo. + + ```python + time.sleep(10) + ``` + +1. Desde el terminal de VS Code, ejecuta lo siguiente para ejecutar tu aplicación en Python: + + ```sh + python3 app.py + ``` + + Deberías ver los valores de temperatura en la consola. Usa algo para calentar el sensor, como presionar tu pulgar sobre él o usar un ventilador, para observar cómo cambian los valores: + + ```output + pi@raspberrypi:~/temperature-sensor $ python3 app.py + Temperature 26°C + Temperature 26°C + Temperature 28°C + Temperature 30°C + Temperature 32°C + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-temperature/pi](../../../../../2-farm/lessons/1-predict-plant-growth/code-temperature/pi). + +😀 ¡Tu programa del sensor de temperatura fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/1-predict-plant-growth/single-board-computer-temp-publish.md b/translations/es/2-farm/lessons/1-predict-plant-growth/single-board-computer-temp-publish.md new file mode 100644 index 00000000..6107f425 --- /dev/null +++ b/translations/es/2-farm/lessons/1-predict-plant-growth/single-board-computer-temp-publish.md @@ -0,0 +1,71 @@ + +# Publicar temperatura - Hardware IoT Virtual y Raspberry Pi + +En esta parte de la lección, publicarás los valores de temperatura detectados por el Raspberry Pi o el Dispositivo IoT Virtual a través de MQTT para que puedan ser utilizados posteriormente en el cálculo de GDD. + +## Publicar la temperatura + +Una vez que se haya leído la temperatura, se puede publicar a través de MQTT a algún código 'servidor' que leerá los valores y los almacenará listos para ser utilizados en un cálculo de GDD. + +### Tarea - publicar la temperatura + +Programa el dispositivo para publicar los datos de temperatura. + +1. Abre el proyecto de la aplicación `temperature-sensor` si aún no está abierto. + +1. Repite los pasos que realizaste en la lección 4 para conectarte a MQTT y enviar telemetría. Utilizarás el mismo broker público de Mosquitto. + + Los pasos para esto son: + + - Agregar el paquete pip de MQTT. + - Agregar el código para conectarte al broker MQTT. + - Agregar el código para publicar telemetría. + + > ⚠️ Consulta las [instrucciones para conectarte a MQTT](../../../1-getting-started/lessons/4-connect-internet/single-board-computer-mqtt.md) y las [instrucciones para enviar telemetría](../../../1-getting-started/lessons/4-connect-internet/single-board-computer-telemetry.md) de la lección 4 si es necesario. + +1. Asegúrate de que el `client_name` refleje el nombre de este proyecto: + + ```python + client_name = id + 'temperature_sensor_client' + ``` + +1. Para la telemetría, en lugar de enviar un valor de luz, envía el valor de temperatura leído del sensor DHT en una propiedad del documento JSON llamada `temperature`: + + ```python + _, temp = sensor.read() + telemetry = json.dumps({'temperature' : temp}) + ``` + +1. No es necesario leer el valor de temperatura con mucha frecuencia, ya que no cambiará mucho en un corto período de tiempo. Por lo tanto, establece el `time.sleep` en 10 minutos: + + ```cpp + time.sleep(10 * 60); + ``` + + > 💁 La función `sleep` toma el tiempo en segundos, por lo que para hacerlo más fácil de leer, el valor se pasa como el resultado de un cálculo. 60 segundos en un minuto, así que 10 x (60 segundos en un minuto) da un retraso de 10 minutos. + +1. Ejecuta el código de la misma manera que ejecutaste el código de la parte anterior de la tarea. Si estás utilizando un dispositivo IoT virtual, asegúrate de que la aplicación CounterFit esté ejecutándose y que los sensores de humedad y temperatura hayan sido creados en los pines correctos. + + ```output + pi@raspberrypi:~/temperature-sensor $ python3 app.py + MQTT connected! + Sending telemetry {"temperature": 25} + Sending telemetry {"temperature": 25} + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-publish-temperature/virtual-device](../../../../../2-farm/lessons/1-predict-plant-growth/code-publish-temperature/virtual-device) o en la carpeta [code-publish-temperature/pi](../../../../../2-farm/lessons/1-predict-plant-growth/code-publish-temperature/pi). + +😀 Has publicado exitosamente la temperatura como telemetría desde tu dispositivo. + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/1-predict-plant-growth/virtual-device-temp.md b/translations/es/2-farm/lessons/1-predict-plant-growth/virtual-device-temp.md new file mode 100644 index 00000000..83ac2dfd --- /dev/null +++ b/translations/es/2-farm/lessons/1-predict-plant-growth/virtual-device-temp.md @@ -0,0 +1,154 @@ + +# Medir la temperatura - Hardware IoT Virtual + +En esta parte de la lección, agregarás un sensor de temperatura a tu dispositivo IoT virtual. + +## Hardware Virtual + +El dispositivo IoT virtual usará un sensor simulado de Humedad y Temperatura Digital Grove. Esto mantiene este laboratorio igual que usar un Raspberry Pi con un sensor físico Grove DHT11. + +El sensor combina un **sensor de temperatura** con un **sensor de humedad**, pero en este laboratorio solo te interesará el componente del sensor de temperatura. En un dispositivo IoT físico, el sensor de temperatura sería un [termistor](https://wikipedia.org/wiki/Thermistor) que mide la temperatura detectando un cambio en la resistencia a medida que cambia la temperatura. Los sensores de temperatura suelen ser sensores digitales que convierten internamente la resistencia medida en una temperatura en grados Celsius (o Kelvin, o Fahrenheit). + +### Agregar los sensores a CounterFit + +Para usar un sensor virtual de humedad y temperatura, necesitas agregar los dos sensores a la aplicación CounterFit. + +#### Tarea - agregar los sensores a CounterFit + +Agrega los sensores de humedad y temperatura a la aplicación CounterFit. + +1. Crea una nueva aplicación de Python en tu computadora en una carpeta llamada `temperature-sensor` con un único archivo llamado `app.py`, un entorno virtual de Python, y agrega los paquetes pip de CounterFit. + + > ⚠️ Puedes consultar [las instrucciones para crear y configurar un proyecto de Python de CounterFit en la lección 1 si es necesario](../../../1-getting-started/lessons/1-introduction-to-iot/virtual-device.md). + +1. Instala un paquete adicional de Pip para instalar un shim de CounterFit para el sensor DHT11. Asegúrate de instalarlo desde una terminal con el entorno virtual activado. + + ```sh + pip install counterfit-shims-seeed-python-dht + ``` + +1. Asegúrate de que la aplicación web de CounterFit esté en ejecución. + +1. Crea un sensor de humedad: + + 1. En el cuadro *Create sensor* en el panel *Sensors*, despliega el cuadro *Sensor type* y selecciona *Humidity*. + + 1. Deja las *Units* configuradas en *Percentage*. + + 1. Asegúrate de que el *Pin* esté configurado en *5*. + + 1. Selecciona el botón **Add** para crear el sensor de humedad en el Pin 5. + + ![Configuración del sensor de humedad](../../../../../translated_images/counterfit-create-humidity-sensor.2750e27b6f30e09cf4e22101defd5252710717620816ab41ba688f91f757c49a.es.png) + + El sensor de humedad será creado y aparecerá en la lista de sensores. + + ![Sensor de humedad creado](../../../../../translated_images/counterfit-humidity-sensor.7b12f7f339e430cb26c8211d2dba4ef75261b353a01da0932698b5bebd693f27.es.png) + +1. Crea un sensor de temperatura: + + 1. En el cuadro *Create sensor* en el panel *Sensors*, despliega el cuadro *Sensor type* y selecciona *Temperature*. + + 1. Deja las *Units* configuradas en *Celsius*. + + 1. Asegúrate de que el *Pin* esté configurado en *6*. + + 1. Selecciona el botón **Add** para crear el sensor de temperatura en el Pin 6. + + ![Configuración del sensor de temperatura](../../../../../translated_images/counterfit-create-temperature-sensor.199350ed34f7343d79dccbe95eaf6c11d2121f03d1c35ab9613b330c23f39b29.es.png) + + El sensor de temperatura será creado y aparecerá en la lista de sensores. + + ![Sensor de temperatura creado](../../../../../translated_images/counterfit-temperature-sensor.f0560236c96a9016bafce7f6f792476fe3367bc6941a1f7d5811d144d4bcbfff.es.png) + +## Programar la aplicación del sensor de temperatura + +Ahora se puede programar la aplicación del sensor de temperatura utilizando los sensores de CounterFit. + +### Tarea - programar la aplicación del sensor de temperatura + +Programa la aplicación del sensor de temperatura. + +1. Asegúrate de que la aplicación `temperature-sensor` esté abierta en VS Code. + +1. Abre el archivo `app.py`. + +1. Agrega el siguiente código al inicio de `app.py` para conectar la aplicación a CounterFit: + + ```python + from counterfit_connection import CounterFitConnection + CounterFitConnection.init('127.0.0.1', 5000) + ``` + +1. Agrega el siguiente código al archivo `app.py` para importar las bibliotecas necesarias: + + ```python + import time + from counterfit_shims_seeed_python_dht import DHT + ``` + + La declaración `from seeed_dht import DHT` importa la clase `DHT` para interactuar con un sensor virtual de temperatura Grove utilizando un shim del módulo `counterfit_shims_seeed_python_dht`. + +1. Agrega el siguiente código después del anterior para crear una instancia de la clase que gestiona el sensor virtual de humedad y temperatura: + + ```python + sensor = DHT("11", 5) + ``` + + Esto declara una instancia de la clase `DHT` que gestiona el sensor virtual de **H**umedad y **T**emperatura **D**igital. El primer parámetro indica que el sensor utilizado es un sensor virtual *DHT11*. El segundo parámetro indica que el sensor está conectado al puerto `5`. + + > 💁 CounterFit simula este sensor combinado de humedad y temperatura conectándose a 2 sensores: un sensor de humedad en el pin indicado al crear la clase `DHT`, y un sensor de temperatura que funciona en el pin siguiente. Si el sensor de humedad está en el pin 5, el shim espera que el sensor de temperatura esté en el pin 6. + +1. Agrega un bucle infinito después del código anterior para consultar el valor del sensor de temperatura e imprimirlo en la consola: + + ```python + while True: + _, temp = sensor.read() + print(f'Temperature {temp}°C') + ``` + + La llamada a `sensor.read()` devuelve una tupla de humedad y temperatura. Solo necesitas el valor de la temperatura, por lo que se ignora la humedad. El valor de la temperatura se imprime en la consola. + +1. Agrega una pequeña pausa de diez segundos al final del `loop`, ya que no es necesario verificar continuamente los niveles de temperatura. Una pausa reduce el consumo de energía del dispositivo. + + ```python + time.sleep(10) + ``` + +1. Desde la Terminal de VS Code con un entorno virtual activado, ejecuta lo siguiente para ejecutar tu aplicación de Python: + + ```sh + python app.py + ``` + +1. Desde la aplicación CounterFit, cambia el valor del sensor de temperatura que será leído por la aplicación. Puedes hacerlo de dos maneras: + + * Ingresa un número en el cuadro *Value* del sensor de temperatura y selecciona el botón **Set**. El número que ingreses será el valor devuelto por el sensor. + + * Marca la casilla *Random* e ingresa un valor *Min* y *Max*, luego selecciona el botón **Set**. Cada vez que el sensor lea un valor, leerá un número aleatorio entre *Min* y *Max*. + + Deberías ver los valores que configures apareciendo en la consola. Cambia el *Value* o la configuración de *Random* para ver cómo cambia el valor. + + ```output + (.venv) ➜ temperature-sensor python app.py + Temperature 28.25°C + Temperature 30.71°C + Temperature 25.17°C + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-temperature/virtual-device](../../../../../2-farm/lessons/1-predict-plant-growth/code-temperature/virtual-device). + +😀 ¡Tu programa del sensor de temperatura fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/1-predict-plant-growth/wio-terminal-temp-publish.md b/translations/es/2-farm/lessons/1-predict-plant-growth/wio-terminal-temp-publish.md new file mode 100644 index 00000000..ffc30c0b --- /dev/null +++ b/translations/es/2-farm/lessons/1-predict-plant-growth/wio-terminal-temp-publish.md @@ -0,0 +1,82 @@ + +# Publicar temperatura - Wio Terminal + +En esta parte de la lección, publicarás los valores de temperatura detectados por el Wio Terminal a través de MQTT para que puedan ser utilizados posteriormente para calcular GDD. + +## Publicar la temperatura + +Una vez que se haya leído la temperatura, se puede publicar a través de MQTT a algún código 'servidor' que leerá los valores y los almacenará listos para ser utilizados en un cálculo de GDD. Los microcontroladores no leen la hora de Internet ni rastrean el tiempo con un reloj en tiempo real de forma predeterminada; el dispositivo necesita ser programado para hacerlo, suponiendo que tenga el hardware necesario. + +Para simplificar las cosas en esta lección, el tiempo no se enviará junto con los datos del sensor; en su lugar, puede ser agregado por el código del servidor más tarde cuando reciba los mensajes. + +### Tarea + +Programa el dispositivo para publicar los datos de temperatura. + +1. Abre el proyecto `temperature-sensor` de Wio Terminal. + +1. Repite los pasos que realizaste en la lección 4 para conectarte a MQTT y enviar telemetría. Utilizarás el mismo broker público de Mosquitto. + + Los pasos para esto son: + + - Agregar las bibliotecas Seeed WiFi y MQTT al archivo `.ini`. + - Agregar el archivo de configuración y el código para conectarse a WiFi. + - Agregar el código para conectarse al broker MQTT. + - Agregar el código para publicar telemetría. + + > ⚠️ Consulta las [instrucciones para conectarte a MQTT](../../../1-getting-started/lessons/4-connect-internet/wio-terminal-mqtt.md) y las [instrucciones para enviar telemetría](../../../1-getting-started/lessons/4-connect-internet/wio-terminal-telemetry.md) de la lección 4 si es necesario. + +1. Asegúrate de que el `CLIENT_NAME` en el archivo de encabezado `config.h` refleje este proyecto: + + ```cpp + const string CLIENT_NAME = ID + "temperature_sensor_client"; + ``` + +1. Para la telemetría, en lugar de enviar un valor de luz, envía el valor de temperatura leído del sensor DHT en una propiedad del documento JSON llamada `temperature` cambiando la función `loop` en `main.cpp`: + + ```cpp + float temp_hum_val[2] = {0}; + dht.readTempAndHumidity(temp_hum_val); + + DynamicJsonDocument doc(1024); + doc["temperature"] = temp_hum_val[1]; + ``` + +1. El valor de la temperatura no necesita ser leído con mucha frecuencia, ya que no cambiará mucho en un corto período de tiempo. Por lo tanto, establece el `delay` en la función `loop` a 10 minutos: + + ```cpp + delay(10 * 60 * 1000); + ``` + + > 💁 La función `delay` toma el tiempo en milisegundos, por lo que para hacerlo más fácil de leer, el valor se pasa como el resultado de un cálculo. 1,000ms en un segundo, 60s en un minuto, así que 10 x (60s en un minuto) x (1000ms en un segundo) da un retraso de 10 minutos. + +1. Carga esto en tu Wio Terminal y utiliza el monitor serial para ver la temperatura siendo enviada al broker MQTT. + + ```output + --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time + --- More details at http://bit.ly/pio-monitor-filters + --- Miniterm on /dev/cu.usbmodem1201 9600,8,N,1 --- + --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + Connecting to WiFi.. + Connected! + Attempting MQTT connection...connected + Sending telemetry {"temperature":25} + Sending telemetry {"temperature":25} + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-publish-temperature/wio-terminal](../../../../../2-farm/lessons/1-predict-plant-growth/code-publish-temperature/wio-terminal). + +😀 Has publicado exitosamente la temperatura como telemetría desde tu dispositivo. + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/1-predict-plant-growth/wio-terminal-temp.md b/translations/es/2-farm/lessons/1-predict-plant-growth/wio-terminal-temp.md new file mode 100644 index 00000000..c017b273 --- /dev/null +++ b/translations/es/2-farm/lessons/1-predict-plant-growth/wio-terminal-temp.md @@ -0,0 +1,143 @@ + +# Medir la temperatura - Wio Terminal + +En esta parte de la lección, agregarás un sensor de temperatura a tu Wio Terminal y leerás los valores de temperatura desde él. + +## Hardware + +El Wio Terminal necesita un sensor de temperatura. + +El sensor que usarás es un [sensor de humedad y temperatura DHT11](https://www.seeedstudio.com/Grove-Temperature-Humidity-Sensor-DHT11.html), que combina 2 sensores en un solo paquete. Este es bastante popular, con varios sensores disponibles comercialmente que combinan temperatura, humedad y, a veces, presión atmosférica. El componente del sensor de temperatura es un termistor de coeficiente de temperatura negativo (NTC), un termistor cuya resistencia disminuye a medida que aumenta la temperatura. + +Este es un sensor digital, por lo que tiene un ADC integrado para crear una señal digital que contiene los datos de temperatura y humedad que el microcontrolador puede leer. + +### Conectar el sensor de temperatura + +El sensor de temperatura Grove se puede conectar al puerto digital del Wio Terminal. + +#### Tarea - conectar el sensor de temperatura + +Conecta el sensor de temperatura. + +![Un sensor de temperatura Grove](../../../../../translated_images/grove-dht11.07f8eafceee170043efbb53e1d15722bd4e00fbaa9ff74290b57e9f66eb82c17.es.png) + +1. Inserta un extremo de un cable Grove en el conector del sensor de humedad y temperatura. Solo encajará de una manera. + +1. Con el Wio Terminal desconectado de tu computadora u otra fuente de alimentación, conecta el otro extremo del cable Grove al conector Grove del lado derecho del Wio Terminal, mirando la pantalla. Este es el conector más alejado del botón de encendido. + +![El sensor de temperatura Grove conectado al conector derecho](../../../../../translated_images/wio-temperature-sensor.2934928f38c7f79a68d24879d2c8986c78244696f931e2e33c293f426ecdc0ad.es.png) + +## Programar el sensor de temperatura + +Ahora se puede programar el Wio Terminal para usar el sensor de temperatura conectado. + +### Tarea - programar el sensor de temperatura + +Programa el dispositivo. + +1. Crea un nuevo proyecto de Wio Terminal usando PlatformIO. Llama a este proyecto `temperature-sensor`. Agrega código en la función `setup` para configurar el puerto serial. + + > ⚠️ Puedes consultar [las instrucciones para crear un proyecto PlatformIO en el proyecto 1, lección 1 si es necesario](../../../1-getting-started/lessons/1-introduction-to-iot/wio-terminal.md#create-a-platformio-project). + +1. Agrega una dependencia de biblioteca para la biblioteca Seeed Grove Humidity and Temperature sensor al archivo `platformio.ini` del proyecto: + + ```ini + lib_deps = + seeed-studio/Grove Temperature And Humidity Sensor @ 1.0.1 + ``` + + > ⚠️ Puedes consultar [las instrucciones para agregar bibliotecas a un proyecto PlatformIO en el proyecto 1, lección 4 si es necesario](../../../1-getting-started/lessons/4-connect-internet/wio-terminal-mqtt.md#install-the-wifi-and-mqtt-arduino-libraries). + +1. Agrega las siguientes directivas `#include` al principio del archivo, debajo del existente `#include `: + + ```cpp + #include + #include + ``` + + Esto importa los archivos necesarios para interactuar con el sensor. El archivo de encabezado `DHT.h` contiene el código para el sensor en sí, y agregar el encabezado `SPI.h` asegura que el código necesario para comunicarse con el sensor se vincule cuando se compile la aplicación. + +1. Antes de la función `setup`, declara el sensor DHT: + + ```cpp + DHT dht(D0, DHT11); + ``` + + Esto declara una instancia de la clase `DHT` que gestiona el sensor de **H**umedad y **T**emperatura **D**igital. Este está conectado al puerto `D0`, el conector Grove del lado derecho del Wio Terminal. El segundo parámetro indica que el sensor que se está utilizando es el sensor *DHT11*; la biblioteca que estás usando admite otras variantes de este sensor. + +1. En la función `setup`, agrega código para configurar la conexión serial: + + ```cpp + void setup() + { + Serial.begin(9600); + + while (!Serial) + ; // Wait for Serial to be ready + + delay(1000); + } + ``` + +1. Al final de la función `setup`, después del último `delay`, agrega una llamada para iniciar el sensor DHT: + + ```cpp + dht.begin(); + ``` + +1. En la función `loop`, agrega código para llamar al sensor e imprimir la temperatura en el puerto serial: + + ```cpp + void loop() + { + float temp_hum_val[2] = {0}; + dht.readTempAndHumidity(temp_hum_val); + Serial.print("Temperature: "); + Serial.print(temp_hum_val[1]); + Serial.println ("°C"); + + delay(10000); + } + ``` + + Este código declara un arreglo vacío de 2 flotantes y lo pasa a la llamada a `readTempAndHumidity` en la instancia `DHT`. Esta llamada llena el arreglo con 2 valores: la humedad se coloca en el elemento 0 del arreglo (recuerda que en C++ los arreglos son basados en 0, por lo que el elemento 0 es el 'primero' en el arreglo), y la temperatura se coloca en el elemento 1. + + La temperatura se lee del elemento 1 del arreglo y se imprime en el puerto serial. + + > 🇺🇸 La temperatura se lee en Celsius. Para los estadounidenses, para convertir esto a Fahrenheit, divide el valor en Celsius leído entre 5, luego multiplícalo por 9 y luego suma 32. Por ejemplo, una lectura de temperatura de 20°C se convierte en ((20/5)*9) + 32 = 68°F. + +1. Compila y sube el código al Wio Terminal. + + > ⚠️ Puedes consultar [las instrucciones para crear un proyecto PlatformIO en el proyecto 1, lección 1 si es necesario](../../../1-getting-started/lessons/1-introduction-to-iot/wio-terminal.md#write-the-hello-world-app). + +1. Una vez subido, puedes monitorear la temperatura usando el monitor serial: + + ```output + > Executing task: platformio device monitor < + + --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time + --- More details at http://bit.ly/pio-monitor-filters + --- Miniterm on /dev/cu.usbmodem1201 9600,8,N,1 --- + --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + Temperature: 25.00°C + Temperature: 25.00°C + Temperature: 25.00°C + Temperature: 24.00°C + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-temperature/wio-terminal](../../../../../2-farm/lessons/1-predict-plant-growth/code-temperature/wio-terminal). + +😀 ¡Tu programa del sensor de temperatura fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/2-detect-soil-moisture/README.md b/translations/es/2-farm/lessons/2-detect-soil-moisture/README.md new file mode 100644 index 00000000..e5ee9eac --- /dev/null +++ b/translations/es/2-farm/lessons/2-detect-soil-moisture/README.md @@ -0,0 +1,169 @@ + +C, pronunciado como *I-cuadrado-C*, es un protocolo multi-controlador y multi-periférico, donde cualquier dispositivo conectado puede actuar como controlador o periférico comunicándose a través del bus I²C (el nombre para un sistema de comunicación que transfiere datos). Los datos se envían como paquetes dirigidos, y cada paquete contiene la dirección del dispositivo conectado al que está destinado. + +> 💁 Este modelo solía denominarse maestro/esclavo, pero esta terminología está siendo eliminada debido a su asociación con la esclavitud. La [Open Source Hardware Association ha adoptado los términos controlador/periférico](https://www.oshwa.org/a-resolution-to-redefine-spi-signal-names/), aunque aún puedes encontrar referencias a la terminología anterior. + +Los dispositivos tienen una dirección que se utiliza cuando se conectan al bus I²C, y generalmente está codificada en el dispositivo. Por ejemplo, cada tipo de sensor Grove de Seeed tiene la misma dirección, por lo que todos los sensores de luz tienen la misma dirección, todos los botones tienen la misma dirección, que es diferente de la dirección del sensor de luz. Algunos dispositivos permiten cambiar la dirección, modificando configuraciones de jumpers o soldando pines. + +I²C tiene un bus compuesto por 2 cables principales, junto con 2 cables de alimentación: + +| Cable | Nombre | Descripción | +| ---- | --------- | ----------- | +| SDA | Datos en serie | Este cable se utiliza para enviar datos entre dispositivos. | +| SCL | Reloj en serie | Este cable envía una señal de reloj a una velocidad establecida por el controlador. | +| VCC | Colector común de voltaje | La fuente de alimentación para los dispositivos. Este cable está conectado a los cables SDA y SCL para proporcionarles energía a través de una resistencia pull-up que apaga la señal cuando ningún dispositivo actúa como controlador. | +| GND | Tierra | Proporciona una tierra común para el circuito eléctrico. | + +![Bus I2C con 3 dispositivos conectados a los cables SDA y SCL, compartiendo un cable de tierra común](../../../../../translated_images/i2c.83da845dde02256bdd462dbe0d5145461416b74930571b89d1ae142841eeb584.es.png) + +Para enviar datos, un dispositivo emitirá una condición de inicio para indicar que está listo para enviar datos. Luego se convertirá en el controlador. El controlador envía la dirección del dispositivo con el que desea comunicarse, junto con la indicación de si quiere leer o escribir datos. Después de que los datos han sido transmitidos, el controlador envía una condición de parada para indicar que ha terminado. Después de esto, otro dispositivo puede convertirse en el controlador y enviar o recibir datos. + +2C tiene límites de velocidad, con 3 modos diferentes que funcionan a velocidades fijas. El más rápido es el modo de Alta Velocidad con una velocidad máxima de 3.4Mbps (megabits por segundo), aunque muy pocos dispositivos admiten esa velocidad. Por ejemplo, la Raspberry Pi está limitada al modo rápido a 400Kbps (kilobits por segundo). El modo estándar funciona a 100Kbps. + +> 💁 Si estás utilizando una Raspberry Pi con un Grove Base hat como tu hardware IoT, podrás ver varios conectores I2C en la placa que puedes usar para comunicarte con sensores I2C. Los sensores analógicos Grove también utilizan I2C con un ADC para enviar valores analógicos como datos digitales, por lo que el sensor de luz que usaste simuló un pin analógico, con el valor enviado a través de I2C, ya que la Raspberry Pi solo admite pines digitales. + +### Receptor-transmisor asíncrono universal (UART) + +UART implica circuitos físicos que permiten que dos dispositivos se comuniquen. Cada dispositivo tiene 2 pines de comunicación: transmitir (Tx) y recibir (Rx), con el pin Tx del primer dispositivo conectado al pin Rx del segundo, y el pin Tx del segundo dispositivo conectado al pin Rx del primero. Esto permite que los datos se envíen en ambas direcciones. + +* El dispositivo 1 transmite datos desde su pin Tx, que son recibidos por el dispositivo 2 en su pin Rx. +* El dispositivo 1 recibe datos en su pin Rx que son transmitidos por el dispositivo 2 desde su pin Tx. + +![UART con el pin Tx de un chip conectado al pin Rx de otro, y viceversa](../../../../../translated_images/uart.d0dbd3fb9e3728c6ee1995c8206f3cdb13cdfd208f13745e8ef6854cab75e421.es.png) + +> 🎓 Los datos se envían un bit a la vez, y esto se conoce como comunicación *serial*. La mayoría de los sistemas operativos y microcontroladores tienen *puertos seriales*, es decir, conexiones que pueden enviar y recibir datos seriales disponibles para tu código. + +Los dispositivos UART tienen una [tasa de baudios](https://wikipedia.org/wiki/Symbol_rate) (también conocida como tasa de símbolos), que es la velocidad a la que los datos se enviarán y recibirán en bits por segundo. Una tasa de baudios común es 9,600, lo que significa que se envían 9,600 bits (0s y 1s) de datos cada segundo. + +UART utiliza bits de inicio y parada: envía un bit de inicio para indicar que está a punto de enviar un byte (8 bits) de datos, y luego un bit de parada después de enviar los 8 bits. + +La velocidad de UART depende del hardware, pero incluso las implementaciones más rápidas no superan los 6.5 Mbps (megabits por segundo, o millones de bits, 0 o 1, enviados por segundo). + +Puedes usar UART sobre pines GPIO: puedes configurar un pin como Tx y otro como Rx, y luego conectarlos a otro dispositivo. + +> 💁 Si estás utilizando una Raspberry Pi con un Grove Base hat como tu hardware IoT, podrás ver un conector UART en la placa que puedes usar para comunicarte con sensores que utilizan el protocolo UART. + +### Interfaz Periférica Serial (SPI) + +SPI está diseñado para comunicarse a corta distancia, como en un microcontrolador para interactuar con un dispositivo de almacenamiento como memoria flash. Se basa en un modelo de controlador/periférico con un único controlador (generalmente el procesador del dispositivo IoT) interactuando con múltiples periféricos. El controlador controla todo seleccionando un periférico y enviando o solicitando datos. + +> 💁 Al igual que I2C, los términos controlador y periférico son cambios recientes, por lo que es posible que veas los términos más antiguos aún en uso. + +Los controladores SPI utilizan 3 cables, junto con 1 cable adicional por periférico. Los periféricos utilizan 4 cables. Estos cables son: + +| Cable | Nombre | Descripción | +| ---- | --------- | ----------- | +| COPI | Salida del controlador, entrada del periférico | Este cable es para enviar datos del controlador al periférico. | +| CIPO | Entrada del controlador, salida del periférico | Este cable es para enviar datos del periférico al controlador. | +| SCLK | Reloj serial | Este cable envía una señal de reloj a una velocidad establecida por el controlador. | +| CS | Selección de chip | El controlador tiene múltiples cables, uno por periférico, y cada cable se conecta al cable CS en el periférico correspondiente. | + +![SPI con un controlador y dos periféricos](../../../../../translated_images/spi.297431d6f98b386b4ff88aea44ce9c1e7acfb1ef69c7e4e388a7aa97b6948e24.es.png) + +El cable CS se utiliza para activar un periférico a la vez, comunicándose a través de los cables COPI y CIPO. Cuando el controlador necesita cambiar de periférico, desactiva el cable CS conectado al periférico actualmente activo, y luego activa el cable conectado al periférico con el que desea comunicarse a continuación. + +SPI es *full-duplex*, lo que significa que el controlador puede enviar y recibir datos al mismo tiempo desde el mismo periférico utilizando los cables COPI y CIPO. SPI utiliza una señal de reloj en el cable SCLK para mantener los dispositivos sincronizados, por lo que, a diferencia de enviar directamente a través de UART, no necesita bits de inicio y parada. + +No hay límites de velocidad definidos para SPI, con implementaciones que a menudo pueden transmitir múltiples megabytes de datos por segundo. + +Los kits de desarrollo IoT suelen admitir SPI en algunos de los pines GPIO. Por ejemplo, en una Raspberry Pi puedes usar los pines GPIO 19, 21, 23, 24 y 26 para SPI. + +### Inalámbrico + +Algunos sensores pueden comunicarse a través de protocolos inalámbricos estándar, como Bluetooth (principalmente Bluetooth Low Energy, o BLE), LoRaWAN (un protocolo de red de bajo consumo de **Lo**ng **Ra**nge), o WiFi. Estos permiten sensores remotos que no están físicamente conectados a un dispositivo IoT. + +Un ejemplo de esto son los sensores comerciales de humedad del suelo. Estos medirán la humedad del suelo en un campo y luego enviarán los datos a través de LoRaWAN a un dispositivo concentrador, que procesará los datos o los enviará a través de Internet. Esto permite que el sensor esté lejos del dispositivo IoT que gestiona los datos, reduciendo el consumo de energía y la necesidad de grandes redes WiFi o cables largos. + +BLE es popular para sensores avanzados como rastreadores de actividad física que funcionan en la muñeca. Estos combinan múltiples sensores y envían los datos del sensor a un dispositivo IoT en forma de tu teléfono a través de BLE. + +✅ ¿Tienes algún sensor Bluetooth contigo, en tu casa o en tu escuela? Estos podrían incluir sensores de temperatura, sensores de ocupación, rastreadores de dispositivos y dispositivos de fitness. + +Una forma popular para que los dispositivos comerciales se conecten es Zigbee. Zigbee utiliza WiFi para formar redes de malla entre dispositivos, donde cada dispositivo se conecta a tantos dispositivos cercanos como sea posible, formando una gran cantidad de conexiones como una telaraña. Cuando un dispositivo quiere enviar un mensaje a Internet, puede enviarlo a los dispositivos más cercanos, que luego lo reenvían a otros dispositivos cercanos y así sucesivamente, hasta que llega a un coordinador y puede enviarse a Internet. + +> 🐝 El nombre Zigbee hace referencia al baile de meneo de las abejas melíferas después de regresar a la colmena. + +## Medir los niveles de humedad en el suelo + +Puedes medir el nivel de humedad en el suelo utilizando un sensor de humedad del suelo, un dispositivo IoT y una planta de interior o un parche de suelo cercano. + +### Tarea - medir la humedad del suelo + +Sigue la guía correspondiente para medir la humedad del suelo utilizando tu dispositivo IoT: + +* [Arduino - Wio Terminal](wio-terminal-soil-moisture.md) +* [Computadora de placa única - Raspberry Pi](pi-soil-moisture.md) +* [Computadora de placa única - Dispositivo virtual](virtual-device-soil-moisture.md) + +## Calibración de sensores + +Los sensores dependen de medir propiedades eléctricas como la resistencia o la capacitancia. + +> 🎓 La resistencia, medida en ohmios (Ω), es cuánta oposición hay a la corriente eléctrica que viaja a través de algo. Cuando se aplica un voltaje a un material, la cantidad de corriente que pasa a través de él depende de la resistencia del material. Puedes leer más en la [página de resistencia eléctrica en Wikipedia](https://wikipedia.org/wiki/Electrical_resistance_and_conductance). + +> 🎓 La capacitancia, medida en faradios (F), es la capacidad de un componente o circuito para recolectar y almacenar energía eléctrica. Puedes leer más sobre capacitancia en la [página de capacitancia en Wikipedia](https://wikipedia.org/wiki/Capacitance). + +Estas mediciones no siempre son útiles: imagina un sensor de temperatura que te diera una medición de 22.5KΩ. En cambio, el valor medido necesita convertirse en una unidad útil mediante la calibración, es decir, igualar los valores medidos con la cantidad medida para permitir que las nuevas mediciones se conviertan a la unidad correcta. + +Algunos sensores vienen pre-calibrados. Por ejemplo, el sensor de temperatura que usaste en la última lección ya estaba calibrado para que pudiera devolver una medición de temperatura en °C. En la fábrica, el primer sensor creado se expondría a una gama de temperaturas conocidas y se mediría la resistencia. Esto luego se usaría para construir un cálculo que pueda convertir del valor medido en Ω (la unidad de resistencia) a °C. + +> 💁 La fórmula para calcular la resistencia a partir de la temperatura se llama la [ecuación de Steinhart–Hart](https://wikipedia.org/wiki/Steinhart–Hart_equation). + +### Calibración del sensor de humedad del suelo + +La humedad del suelo se mide utilizando contenido de agua gravimétrico o volumétrico. + +* Gravimétrico es el peso del agua en una unidad de peso de suelo medido, como el número de kilogramos de agua por kilogramo de suelo seco. +* Volumétrico es el volumen de agua en una unidad de volumen de suelo medido, como el número de metros cúbicos de agua por metros cúbicos de suelo seco. + +> 🇺🇸 Para los estadounidenses, debido a la consistencia de las unidades, estos pueden medirse en libras en lugar de kilogramos o pies cúbicos en lugar de metros cúbicos. + +Los sensores de humedad del suelo miden resistencia eléctrica o capacitancia: esto no solo varía según la humedad del suelo, sino también según el tipo de suelo, ya que los componentes en el suelo pueden cambiar sus características eléctricas. Idealmente, los sensores deben calibrarse, es decir, tomar lecturas del sensor y compararlas con mediciones obtenidas utilizando un enfoque más científico. Por ejemplo, un laboratorio puede calcular la humedad gravimétrica del suelo utilizando muestras de un campo específico tomadas unas pocas veces al año, y estos números se utilizan para calibrar el sensor, igualando la lectura del sensor con la humedad gravimétrica del suelo. + +![Un gráfico de voltaje vs contenido de humedad del suelo](../../../../../translated_images/soil-moisture-to-voltage.df86d80cda1587008f312431ed5f79eb6c50c58d4fbc25a6763c5e9127c3106b.es.png) + +El gráfico anterior muestra cómo calibrar un sensor. El voltaje se captura para una muestra de suelo que luego se mide en un laboratorio comparando el peso húmedo con el peso seco (midiendo el peso húmedo, luego secándolo en un horno y midiendo el peso seco). Una vez que se han tomado algunas lecturas, esto puede graficarse y ajustarse una línea a los puntos. Esta línea luego puede usarse para convertir las lecturas del sensor de humedad del suelo tomadas por un dispositivo IoT en mediciones reales de humedad del suelo. + +💁 Para los sensores de humedad del suelo resistivos, el voltaje aumenta a medida que aumenta la humedad del suelo. Para los sensores de humedad del suelo capacitivos, el voltaje disminuye a medida que aumenta la humedad del suelo, por lo que los gráficos para estos se inclinarían hacia abajo, no hacia arriba. + +![Un valor de humedad del suelo interpolado desde el gráfico](../../../../../translated_images/soil-moisture-to-voltage-with-reading.681cb3e1f8b68caf5547dbf1415851c82e201edfb78face16fc98da4051ed9b2.es.png) + +El gráfico anterior muestra una lectura de voltaje de un sensor de humedad del suelo, y al seguir esa lectura hasta la línea en el gráfico, se puede calcular la humedad real del suelo. + +Este enfoque significa que el agricultor solo necesita obtener algunas mediciones de laboratorio para un campo, luego puede usar dispositivos IoT para medir la humedad del suelo, acelerando drásticamente el tiempo para tomar mediciones. + +--- + +## 🚀 Desafío + +Los sensores de humedad del suelo resistivos y capacitivos tienen varias diferencias. ¿Cuáles son estas diferencias y cuál tipo (si alguno) es el mejor para que un agricultor lo use? ¿Cambia esta respuesta entre países en desarrollo y desarrollados? + +## Cuestionario posterior a la lección + +[Cuestionario posterior a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/12) + +## Revisión y autoestudio + +Investiga sobre el hardware y los protocolos utilizados por sensores y actuadores: + +* [Página de Wikipedia sobre GPIO](https://wikipedia.org/wiki/General-purpose_input/output) +* [Página de Wikipedia sobre UART](https://wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter) +* [Página de Wikipedia sobre SPI](https://wikipedia.org/wiki/Serial_Peripheral_Interface) +* [Página de Wikipedia sobre I2C](https://wikipedia.org/wiki/I²C) +* [Página de Wikipedia sobre Zigbee](https://wikipedia.org/wiki/Zigbee) + +## Asignación + +[Calibra tu sensor](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/2-detect-soil-moisture/assignment.md b/translations/es/2-farm/lessons/2-detect-soil-moisture/assignment.md new file mode 100644 index 00000000..683a8a06 --- /dev/null +++ b/translations/es/2-farm/lessons/2-detect-soil-moisture/assignment.md @@ -0,0 +1,61 @@ + +# Calibra tu sensor + +## Instrucciones + +En esta lección obtuviste lecturas del sensor de humedad del suelo, medidas como valores de 0-1023. Para convertir estos valores en lecturas reales de humedad del suelo, necesitas calibrar tu sensor. Puedes hacerlo tomando lecturas de muestras de suelo y luego calculando el contenido gravimétrico de humedad del suelo a partir de estas muestras. + +Necesitarás repetir estos pasos varias veces para obtener las lecturas necesarias, utilizando suelos con diferentes niveles de humedad cada vez. + +1. Toma una lectura de humedad del suelo utilizando el sensor de humedad del suelo. Anota esta lectura. + +1. Toma una muestra del suelo y pésala. Anota este peso. + +1. Seca el suelo. Un horno cálido a 110°C (230°F) durante unas horas es la mejor opción. También puedes hacerlo al sol o colocarlo en un lugar cálido y seco hasta que el suelo esté completamente seco. Debe quedar pulverizado y suelto. + + > 💁 En un laboratorio, para obtener resultados más precisos, deberías secar el suelo en un horno durante 48-72 horas. Si tu escuela tiene hornos de secado, consulta si puedes utilizarlos para secar las muestras por más tiempo. Cuanto más tiempo, más seco estará el suelo y más precisos serán los resultados. + +1. Pesa el suelo nuevamente. + + > 🔥 Si lo secaste en un horno, asegúrate de que se haya enfriado primero. + +La humedad gravimétrica del suelo se calcula como: + +![La humedad del suelo % es el peso húmedo menos el peso seco, dividido por el peso seco, multiplicado por 100](../../../../../translated_images/gsm-calculation.6da38c6201eec14e7573bb2647aa18892883193553d23c9d77e5dc681522dfb2.es.png) + +* W - el peso del suelo húmedo +* W - el peso del suelo seco + +Por ejemplo, supongamos que tienes una muestra de suelo que pesa 212g húmeda y 197g seca. + +![El cálculo completado](../../../../../translated_images/gsm-calculation-example.99f9803b4f29e97668e7c15412136c0c399ab12dbba0b89596fdae9d8aedb6fb.es.png) + +* W = 212g +* W = 197g +* 212 - 197 = 15 +* 15 / 197 = 0.076 +* 0.076 * 100 = 7.6% + +En este ejemplo, el suelo tiene una humedad gravimétrica del 7.6%. + +Una vez que tengas las lecturas de al menos 3 muestras, traza un gráfico del porcentaje de humedad del suelo frente a la lectura del sensor de humedad del suelo y añade una línea que se ajuste mejor a los puntos. Luego, puedes usar esto para calcular el contenido gravimétrico de humedad del suelo para una lectura específica del sensor leyendo el valor de la línea. + +## Rúbrica + +| Criterios | Ejemplar | Adecuado | Necesita Mejorar | +| --------- | -------- | -------- | ---------------- | +| Recopilar datos de calibración | Captura al menos 3 muestras de calibración | Captura al menos 2 muestras de calibración | Captura al menos 1 muestra de calibración | +| Realizar una lectura calibrada | Traza exitosamente el gráfico de calibración y realiza una lectura del sensor, convirtiéndola en contenido gravimétrico de humedad del suelo | Traza exitosamente el gráfico de calibración | No logra trazar el gráfico | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/2-detect-soil-moisture/pi-soil-moisture.md b/translations/es/2-farm/lessons/2-detect-soil-moisture/pi-soil-moisture.md new file mode 100644 index 00000000..2c79d08e --- /dev/null +++ b/translations/es/2-farm/lessons/2-detect-soil-moisture/pi-soil-moisture.md @@ -0,0 +1,25 @@ + +# Medir la humedad del suelo - Raspberry Pi + +En esta parte de la lección, agregarás un sensor capacitivo de humedad del suelo a tu Raspberry Pi y leerás valores de él. + +## Hardware + +La Raspberry Pi necesita un sensor capacitivo de humedad del suelo. + +El sensor que usarás es un [Sensor Capacitivo de Humedad del Suelo](https://www.seeedstudio.com/Grove-Capacitive-Moisture-Sensor-Corrosion-Resistant.html), que mide la humedad del suelo detectando la capacitancia del mismo, una propiedad que cambia a medida que varía la humedad del suelo. A medida que aumenta la humedad del suelo, el voltaje disminuye. + +Este es un sensor analógico, por lo que utiliza un pin analógico y el ADC de 10 bits en el Grove Base Hat de la Pi para convertir el voltaje en una señal digital de 1-1,023. Luego, esta señal se envía a través de I + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/2-detect-soil-moisture/virtual-device-soil-moisture.md b/translations/es/2-farm/lessons/2-detect-soil-moisture/virtual-device-soil-moisture.md new file mode 100644 index 00000000..2293821d --- /dev/null +++ b/translations/es/2-farm/lessons/2-detect-soil-moisture/virtual-device-soil-moisture.md @@ -0,0 +1,123 @@ + +# Medir la humedad del suelo - Hardware IoT Virtual + +En esta parte de la lección, agregarás un sensor capacitivo de humedad del suelo a tu dispositivo IoT virtual y leerás valores de él. + +## Hardware Virtual + +El dispositivo IoT virtual utilizará un sensor capacitivo de humedad del suelo simulado Grove. Esto mantiene este laboratorio igual que usar un Raspberry Pi con un sensor capacitivo de humedad del suelo físico. + +En un dispositivo IoT físico, el sensor de humedad del suelo sería un sensor capacitivo que mide la humedad del suelo detectando la capacitancia del mismo, una propiedad que cambia a medida que cambia la humedad del suelo. A medida que aumenta la humedad del suelo, el voltaje disminuye. + +Este es un sensor analógico, por lo que utiliza un ADC simulado de 10 bits para reportar un valor entre 1 y 1,023. + +### Agregar el sensor de humedad del suelo a CounterFit + +Para usar un sensor virtual de humedad del suelo, necesitas agregarlo a la aplicación CounterFit. + +#### Tarea - Agregar el sensor de humedad del suelo a CounterFit + +Agrega el sensor de humedad del suelo a la aplicación CounterFit. + +1. Crea una nueva aplicación de Python en tu computadora en una carpeta llamada `soil-moisture-sensor` con un único archivo llamado `app.py` y un entorno virtual de Python, y agrega los paquetes pip de CounterFit. + + > ⚠️ Puedes consultar [las instrucciones para crear y configurar un proyecto de Python en CounterFit en la lección 1 si es necesario](../../../1-getting-started/lessons/1-introduction-to-iot/virtual-device.md). + +1. Asegúrate de que la aplicación web de CounterFit esté ejecutándose. + +1. Crea un sensor de humedad del suelo: + + 1. En el cuadro *Create sensor* en el panel *Sensors*, despliega el cuadro *Sensor type* y selecciona *Soil Moisture*. + + 1. Deja las *Units* configuradas en *NoUnits*. + + 1. Asegúrate de que el *Pin* esté configurado en *0*. + + 1. Selecciona el botón **Add** para crear el sensor *Soil Moisture* en el Pin 0. + + ![Configuración del sensor de humedad del suelo](../../../../../translated_images/counterfit-create-soil-moisture-sensor.35266135a5e0ae68b29a684d7db0d2933a8098b2307d197f7c71577b724603aa.es.png) + + El sensor de humedad del suelo será creado y aparecerá en la lista de sensores. + + ![Sensor de humedad del suelo creado](../../../../../translated_images/counterfit-soil-moisture-sensor.81742b2de0e9de60a3b3b9a2ff8ecc686d428eb6d71820f27a693be26e5aceee.es.png) + +## Programar la aplicación del sensor de humedad del suelo + +La aplicación del sensor de humedad del suelo ahora puede ser programada utilizando los sensores de CounterFit. + +### Tarea - Programar la aplicación del sensor de humedad del suelo + +Programa la aplicación del sensor de humedad del suelo. + +1. Asegúrate de que la aplicación `soil-moisture-sensor` esté abierta en VS Code. + +1. Abre el archivo `app.py`. + +1. Agrega el siguiente código al inicio de `app.py` para conectar la aplicación a CounterFit: + + ```python + from counterfit_connection import CounterFitConnection + CounterFitConnection.init('127.0.0.1', 5000) + ``` + +1. Agrega el siguiente código al archivo `app.py` para importar algunas bibliotecas necesarias: + + ```python + import time + from counterfit_shims_grove.adc import ADC + ``` + + La declaración `import time` importa el módulo `time`, que se utilizará más adelante en esta tarea. + + La declaración `from counterfit_shims_grove.adc import ADC` importa la clase `ADC` para interactuar con un convertidor analógico a digital virtual que puede conectarse a un sensor de CounterFit. + +1. Agrega el siguiente código debajo de esto para crear una instancia de la clase `ADC`: + + ```python + adc = ADC() + ``` + +1. Agrega un bucle infinito que lea desde este ADC en el pin 0 y escriba el resultado en la consola. Este bucle puede luego dormir durante 10 segundos entre lecturas. + + ```python + while True: + soil_moisture = adc.read(0) + print("Soil moisture:", soil_moisture) + + time.sleep(10) + ``` + +1. Desde la aplicación CounterFit, cambia el valor del sensor de humedad del suelo que será leído por la aplicación. Puedes hacerlo de dos maneras: + + * Ingresa un número en el cuadro *Value* del sensor de humedad del suelo y luego selecciona el botón **Set**. El número que ingreses será el valor devuelto por el sensor. + + * Marca la casilla *Random* y establece un valor *Min* y *Max*, luego selecciona el botón **Set**. Cada vez que el sensor lea un valor, leerá un número aleatorio entre *Min* y *Max*. + +1. Ejecuta la aplicación de Python. Verás las mediciones de humedad del suelo escritas en la consola. Cambia el *Value* o la configuración de *Random* para ver cómo cambia el valor. + + ```output + (.venv) ➜ soil-moisture-sensor $ python app.py + Soil moisture: 615 + Soil moisture: 612 + Soil moisture: 498 + Soil moisture: 493 + Soil moisture: 490 + Soil Moisture: 388 + ``` + +> 💁 Puedes encontrar este código en la carpeta [code/virtual-device](../../../../../2-farm/lessons/2-detect-soil-moisture/code/virtual-device). + +😀 ¡Tu programa del sensor de humedad del suelo fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/2-detect-soil-moisture/wio-terminal-soil-moisture.md b/translations/es/2-farm/lessons/2-detect-soil-moisture/wio-terminal-soil-moisture.md new file mode 100644 index 00000000..17caa993 --- /dev/null +++ b/translations/es/2-farm/lessons/2-detect-soil-moisture/wio-terminal-soil-moisture.md @@ -0,0 +1,117 @@ + +# Medir la humedad del suelo - Wio Terminal + +En esta parte de la lección, agregarás un sensor capacitivo de humedad del suelo a tu Wio Terminal y leerás valores de él. + +## Hardware + +El Wio Terminal necesita un sensor capacitivo de humedad del suelo. + +El sensor que usarás es un [Sensor Capacitivo de Humedad del Suelo](https://www.seeedstudio.com/Grove-Capacitive-Moisture-Sensor-Corrosion-Resistant.html), que mide la humedad del suelo detectando la capacitancia del mismo, una propiedad que cambia a medida que varía la humedad del suelo. A medida que aumenta la humedad del suelo, el voltaje disminuye. + +Este es un sensor analógico, por lo que se conecta a los pines analógicos del Wio Terminal, utilizando un ADC integrado para generar un valor de 0 a 1,023. + +### Conecta el sensor de humedad del suelo + +El sensor de humedad del suelo Grove puede conectarse al puerto analógico/digital configurable del Wio Terminal. + +#### Tarea - conectar el sensor de humedad del suelo + +Conecta el sensor de humedad del suelo. + +![Un sensor Grove de humedad del suelo](../../../../../translated_images/grove-capacitive-soil-moisture-sensor.e7f0776cce30e78be5cc5a07839385fd6718857f31b5bf5ad3d0c73c83b2f0ef.es.png) + +1. Inserta un extremo de un cable Grove en el conector del sensor de humedad del suelo. Solo encajará de una manera. + +1. Con el Wio Terminal desconectado de tu computadora u otra fuente de alimentación, conecta el otro extremo del cable Grove al conector Grove del lado derecho del Wio Terminal, mirando la pantalla. Este es el conector más alejado del botón de encendido. + +![El sensor Grove de humedad del suelo conectado al conector derecho](../../../../../translated_images/wio-soil-moisture-sensor.46919b61c3f6cb7497662251b29038ee0e57a4c8b9d071feb996c3b0d7f65aaf.es.png) + +1. Inserta el sensor de humedad del suelo en la tierra. Tiene una 'línea de posición máxima' - una línea blanca a través del sensor. Inserta el sensor hasta esta línea, pero no más allá. + +![El sensor Grove de humedad del suelo en la tierra](../../../../../translated_images/soil-moisture-sensor-in-soil.bfad91002bda5e960f8c51ee64b02ee59b32c8c717e3515a2c945f33e614e403.es.png) + +1. Ahora puedes conectar el Wio Terminal a tu computadora. + +## Programa el sensor de humedad del suelo + +El Wio Terminal ahora puede ser programado para usar el sensor de humedad del suelo conectado. + +### Tarea - programar el sensor de humedad del suelo + +Programa el dispositivo. + +1. Crea un nuevo proyecto de Wio Terminal usando PlatformIO. Llama a este proyecto `soil-moisture-sensor`. Agrega código en la función `setup` para configurar el puerto serial. + + > ⚠️ Puedes consultar [las instrucciones para crear un proyecto PlatformIO en el proyecto 1, lección 1 si es necesario](../../../1-getting-started/lessons/1-introduction-to-iot/wio-terminal.md#create-a-platformio-project). + +1. No existe una biblioteca para este sensor, en su lugar puedes leer desde el pin analógico usando la función [`analogRead`](https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/) incorporada de Arduino. Comienza configurando el pin analógico como entrada para que se puedan leer valores de él, agregando lo siguiente a la función `setup`. + + ```cpp + pinMode(A0, INPUT); + ``` + + Esto configura el pin `A0`, el pin combinado analógico/digital, como un pin de entrada desde el cual se puede leer voltaje. + +1. Agrega lo siguiente a la función `loop` para leer el voltaje de este pin: + + ```cpp + int soil_moisture = analogRead(A0); + ``` + +1. Debajo de este código, agrega el siguiente código para imprimir el valor en el puerto serial: + + ```cpp + Serial.print("Soil Moisture: "); + Serial.println(soil_moisture); + ``` + +1. Finalmente, agrega un retraso al final de 10 segundos: + + ```cpp + delay(10000); + ``` + +1. Compila y sube el código al Wio Terminal. + + > ⚠️ Puedes consultar [las instrucciones para crear un proyecto PlatformIO en el proyecto 1, lección 1 si es necesario](../../../1-getting-started/lessons/1-introduction-to-iot/wio-terminal.md#write-the-hello-world-app). + +1. Una vez subido, puedes monitorear la humedad del suelo usando el monitor serial. Agrega un poco de agua a la tierra o retira el sensor de la tierra y observa cómo cambia el valor. + + ```output + > Executing task: platformio device monitor < + + --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time + --- More details at http://bit.ly/pio-monitor-filters + --- Miniterm on /dev/cu.usbmodem1201 9600,8,N,1 --- + --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + Soil Moisture: 526 + Soil Moisture: 529 + Soil Moisture: 521 + Soil Moisture: 494 + Soil Moisture: 454 + Soil Moisture: 456 + Soil Moisture: 395 + Soil Moisture: 388 + Soil Moisture: 394 + Soil Moisture: 391 + ``` + + En el ejemplo de salida anterior, puedes ver cómo el voltaje disminuye a medida que se agrega agua. + +> 💁 Puedes encontrar este código en la carpeta [code/wio-terminal](../../../../../2-farm/lessons/2-detect-soil-moisture/code/wio-terminal). + +😀 ¡Tu programa para el sensor de humedad del suelo fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/3-automated-plant-watering/README.md b/translations/es/2-farm/lessons/3-automated-plant-watering/README.md new file mode 100644 index 00000000..205bb495 --- /dev/null +++ b/translations/es/2-farm/lessons/3-automated-plant-watering/README.md @@ -0,0 +1,314 @@ + +# Riego automatizado de plantas + +![Una vista general en sketchnote de esta lección](../../../../../translated_images/lesson-7.30b5f577d3cb8e031238751475cb519c7d6dbaea261b5df4643d086ffb2a03bb.es.jpg) + +> Sketchnote por [Nitya Narasimhan](https://github.com/nitya). Haz clic en la imagen para una versión más grande. + +Esta lección fue impartida como parte de la serie [IoT para principiantes Proyecto 2 - Agricultura digital](https://youtube.com/playlist?list=PLmsFUfdnGr3yCutmcVg6eAUEfsGiFXgcx) del [Microsoft Reactor](https://developer.microsoft.com/reactor/?WT.mc_id=academic-17441-jabenn). + +[![Riego automatizado de plantas impulsado por IoT](https://img.youtube.com/vi/g9FfZwv9R58/0.jpg)](https://youtu.be/g9FfZwv9R58) + +## Cuestionario previo a la lección + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/13) + +## Introducción + +En la última lección, aprendiste cómo monitorear la humedad del suelo. En esta lección aprenderás a construir los componentes principales de un sistema de riego automatizado que responde a la humedad del suelo. También aprenderás sobre el tiempo de respuesta: cómo los sensores pueden tardar en reaccionar a los cambios y cómo los actuadores pueden tardar en modificar las propiedades que los sensores están midiendo. + +En esta lección cubriremos: + +* [Controlar dispositivos de alta potencia desde un dispositivo IoT de baja potencia](../../../../../2-farm/lessons/3-automated-plant-watering) +* [Controlar un relé](../../../../../2-farm/lessons/3-automated-plant-watering) +* [Controlar tu planta mediante MQTT](../../../../../2-farm/lessons/3-automated-plant-watering) +* [Tiempo de respuesta de sensores y actuadores](../../../../../2-farm/lessons/3-automated-plant-watering) +* [Agregar temporización al servidor de control de tu planta](../../../../../2-farm/lessons/3-automated-plant-watering) + +## Controlar dispositivos de alta potencia desde un dispositivo IoT de baja potencia + +Los dispositivos IoT utilizan un voltaje bajo. Aunque esto es suficiente para sensores y actuadores de baja potencia como LEDs, es demasiado bajo para controlar hardware más grande, como una bomba de agua utilizada para riego. Incluso las bombas pequeñas que podrías usar para plantas de interior consumen demasiada corriente para un kit de desarrollo IoT y podrían dañar la placa. + +> 🎓 La corriente, medida en amperios (A), es la cantidad de electricidad que fluye a través de un circuito. El voltaje proporciona el empuje, la corriente es cuánto se empuja. Puedes leer más sobre la corriente en la [página de corriente eléctrica en Wikipedia](https://wikipedia.org/wiki/Electric_current). + +La solución a esto es conectar una bomba a una fuente de alimentación externa y usar un actuador para encender la bomba, similar a cómo encenderías una luz. Se necesita una pequeña cantidad de energía (en forma de energía en tu cuerpo) para que tu dedo accione un interruptor, y esto conecta la luz a la electricidad de red que funciona a 110v/240v. + +![Un interruptor de luz enciende la luz](../../../../../translated_images/light-switch.760317ad6ab8bd6d611da5352dfe9c73a94a0822ccec7df3c8bae35da18e1658.es.png) + +> 🎓 [Electricidad de red](https://wikipedia.org/wiki/Mains_electricity) se refiere a la electricidad entregada a hogares y negocios a través de infraestructura nacional en muchas partes del mundo. + +✅ Los dispositivos IoT generalmente pueden proporcionar 3.3V o 5V, con menos de 1 amperio (1A) de corriente. Comparado con la electricidad de red, que suele ser de 230V (120V en América del Norte y 100V en Japón), y puede proporcionar energía para dispositivos que consumen hasta 30A. + +Existen varios actuadores que pueden hacer esto, incluidos dispositivos mecánicos que puedes conectar a interruptores existentes para imitar un dedo encendiéndolos. El más popular es un relé. + +### Relés + +Un relé es un interruptor electromecánico que convierte una señal eléctrica en un movimiento mecánico que enciende un interruptor. El núcleo de un relé es un electroimán. + +> 🎓 [Electroimanes](https://wikipedia.org/wiki/Electromagnet) son imanes que se crean al pasar electricidad a través de una bobina de alambre. Cuando la electricidad está encendida, la bobina se magnetiza. Cuando la electricidad está apagada, la bobina pierde su magnetismo. + +![Cuando está encendido, el electroimán crea un campo magnético, activando el interruptor del circuito de salida](../../../../../translated_images/relay-on.4db16a0fd6b669262fd6699aff3fbcd31b6057c06d90411b6bddc06326d1cf75.es.png) + +En un relé, un circuito de control alimenta el electroimán. Cuando el electroimán está encendido, tira de una palanca que mueve un interruptor, cerrando un par de contactos y completando un circuito de salida. + +![Cuando está apagado, el electroimán no crea un campo magnético, desactivando el interruptor del circuito de salida](../../../../../translated_images/relay-off.c34a178a2960fecdc3c6400d43e633ed11c6746cd653cfb4a768fa097c40394c.es.png) + +Cuando el circuito de control está apagado, el electroimán se apaga, liberando la palanca y abriendo los contactos, apagando el circuito de salida. Los relés son actuadores digitales: una señal alta al relé lo enciende, una señal baja lo apaga. + +El circuito de salida puede usarse para alimentar hardware adicional, como un sistema de riego. El dispositivo IoT puede encender el relé, completando el circuito de salida que alimenta el sistema de riego, y las plantas se riegan. Luego, el dispositivo IoT puede apagar el relé, cortando la energía al sistema de riego y deteniendo el agua. + +![Un relé encendiéndose, activando una bomba que envía agua a una planta](../../../../../images/strawberry-pump.gif) + +En el video anterior, se enciende un relé. Un LED en el relé se ilumina para indicar que está encendido (algunas placas de relé tienen LEDs para indicar si el relé está encendido o apagado), y se envía energía a la bomba, activándola y bombeando agua a una planta. + +> 💁 Los relés también pueden usarse para alternar entre dos circuitos de salida en lugar de encender y apagar uno. A medida que la palanca se mueve, cambia un interruptor de completar un circuito de salida a completar un circuito de salida diferente, generalmente compartiendo una conexión de alimentación común o una conexión de tierra común. + +✅ Investiga: Hay múltiples tipos de relés, con diferencias como si el circuito de control enciende o apaga el relé cuando se aplica energía, o múltiples circuitos de salida. Investiga sobre estos diferentes tipos. + +Cuando la palanca se mueve, generalmente puedes escucharla hacer contacto con el electroimán con un ruido de clic bien definido. + +> 💁 Un relé puede cablearse de manera que al hacer la conexión realmente interrumpa la energía al relé, apagándolo, lo que luego envía energía al relé encendiéndolo nuevamente, y así sucesivamente. Esto significa que el relé hará clic increíblemente rápido, produciendo un ruido de zumbido. Así es como funcionaban algunos de los primeros timbres eléctricos utilizados en puertas. + +### Energía del relé + +El electroimán no necesita mucha energía para activarse y tirar de la palanca, puede controlarse utilizando la salida de 3.3V o 5V de un kit de desarrollo IoT. El circuito de salida puede transportar mucha más energía, dependiendo del relé, incluyendo voltaje de red o incluso niveles de energía más altos para uso industrial. De esta manera, un kit de desarrollo IoT puede controlar un sistema de riego, desde una pequeña bomba para una sola planta, hasta un sistema industrial masivo para toda una granja comercial. + +![Un relé Grove con el circuito de control, circuito de salida y relé etiquetados](../../../../../translated_images/grove-relay-labelled.293e068f5c3c2a199bd7892f2661fdc9e10c920b535cfed317fbd6d1d4ae1168.es.png) + +La imagen anterior muestra un relé Grove. El circuito de control se conecta a un dispositivo IoT y enciende o apaga el relé utilizando 3.3V o 5V. El circuito de salida tiene dos terminales, cualquiera de ellos puede ser alimentación o tierra. El circuito de salida puede manejar hasta 250V a 10A, suficiente para una variedad de dispositivos alimentados por red. Puedes obtener relés que pueden manejar incluso niveles de energía más altos. + +![Una bomba conectada a través de un relé](../../../../../translated_images/pump-wired-to-relay.66c5cfc0d89189900cd601777f5caeb39ee35c6250f6c86bf38feaceedb21fe9.es.png) + +En la imagen anterior, la energía se suministra a una bomba a través de un relé. Hay un cable rojo que conecta el terminal +5V de una fuente de alimentación USB a un terminal del circuito de salida del relé, y otro cable rojo que conecta el otro terminal del circuito de salida a la bomba. Un cable negro conecta la bomba a la tierra de la fuente de alimentación USB. Cuando el relé se enciende, completa el circuito, enviando 5V a la bomba y activándola. + +## Controlar un relé + +Puedes controlar un relé desde tu kit de desarrollo IoT. + +### Tarea - controlar un relé + +Sigue la guía correspondiente para controlar un relé utilizando tu dispositivo IoT: + +* [Arduino - Wio Terminal](wio-terminal-relay.md) +* [Computadora de placa única - Raspberry Pi](pi-relay.md) +* [Computadora de placa única - Dispositivo virtual](virtual-device-relay.md) + +## Controlar tu planta mediante MQTT + +Hasta ahora, tu relé es controlado directamente por el dispositivo IoT basado en una sola lectura de humedad del suelo. En un sistema de riego comercial, la lógica de control estará centralizada, permitiendo tomar decisiones sobre el riego utilizando datos de múltiples sensores y permitiendo que cualquier configuración se cambie en un solo lugar. Para simular esto, puedes controlar el relé mediante MQTT. + +### Tarea - controlar el relé mediante MQTT + +1. Agrega las bibliotecas/pip packages y el código relevantes de MQTT a tu proyecto `soil-moisture-sensor` para conectarte a MQTT. Nombra el ID del cliente como `soilmoisturesensor_client` precedido por tu ID. + + > ⚠️ Puedes consultar [las instrucciones para conectarte a MQTT en el proyecto 1, lección 4 si es necesario](../../../1-getting-started/lessons/4-connect-internet/README.md#connect-your-iot-device-to-mqtt). + +1. Agrega el código del dispositivo relevante para enviar telemetría con las configuraciones de humedad del suelo. Para el mensaje de telemetría, nombra la propiedad `soil_moisture`. + + > ⚠️ Puedes consultar [las instrucciones para enviar telemetría a MQTT en el proyecto 1, lección 4 si es necesario](../../../1-getting-started/lessons/4-connect-internet/README.md#send-telemetry-from-your-iot-device). + +1. Crea un código de servidor local para suscribirte a la telemetría y enviar un comando para controlar el relé en una carpeta llamada `soil-moisture-sensor-server`. Nombra la propiedad en el mensaje de comando `relay_on`, y establece el ID del cliente como `soilmoisturesensor_server` precedido por tu ID. Mantén la misma estructura que el código del servidor que escribiste para el proyecto 1, lección 4, ya que agregarás más código a este más adelante en esta lección. + + > ⚠️ Puedes consultar [las instrucciones para enviar telemetría a MQTT](../../../1-getting-started/lessons/4-connect-internet/README.md#write-the-server-code) y [enviar comandos mediante MQTT](../../../1-getting-started/lessons/4-connect-internet/README.md#send-commands-to-the-mqtt-broker) en el proyecto 1, lección 4 si es necesario. + +1. Agrega el código del dispositivo relevante para controlar el relé a partir de los comandos recibidos, utilizando la propiedad `relay_on` del mensaje. Envía true para `relay_on` si el `soil_moisture` es mayor que 450, de lo contrario envía false, igual que la lógica que agregaste para el dispositivo IoT anteriormente. + + > ⚠️ Puedes consultar [las instrucciones para responder a comandos de MQTT en el proyecto 1, lección 4 si es necesario](../../../1-getting-started/lessons/4-connect-internet/README.md#handle-commands-on-the-iot-device). + +> 💁 Puedes encontrar este código en la carpeta [code-mqtt](../../../../../2-farm/lessons/3-automated-plant-watering/code-mqtt). + +Asegúrate de que el código esté ejecutándose en tu dispositivo y servidor local, y pruébalo cambiando los niveles de humedad del suelo, ya sea modificando los valores enviados por el sensor virtual o cambiando los niveles de humedad del suelo agregando agua o retirando el sensor del suelo. + +## Tiempo de respuesta de sensores y actuadores + +En la lección 3 construiste una luz nocturna: un LED que se enciende tan pronto como un nivel bajo de luz es detectado por un sensor de luz. El sensor de luz detectó un cambio en los niveles de luz instantáneamente, y el dispositivo pudo responder rápidamente, limitado solo por la duración del retraso en la función `loop` o el bucle `while True:`. Como desarrollador de IoT, no siempre puedes confiar en un ciclo de retroalimentación tan rápido. + +### Temporización para la humedad del suelo + +Si realizaste la última lección sobre humedad del suelo utilizando un sensor físico, habrás notado que tomó unos segundos para que la lectura de humedad del suelo bajara después de regar tu planta. Esto no se debe a que el sensor sea lento, sino a que el agua tarda en filtrarse a través del suelo. +💁 Si regaste demasiado cerca del sensor, es posible que hayas notado que la lectura bajó rápidamente y luego volvió a subir. Esto ocurre porque el agua cerca del sensor se dispersa por el resto del suelo, reduciendo la humedad del suelo alrededor del sensor. +![Una medición de humedad del suelo de 658 no cambia durante el riego, solo baja a 320 después de que el agua ha empapado el suelo](../../../../../translated_images/soil-moisture-travel.a0e31af222cf14385de5380dfc32c7b8213960965228b8e4f7b7ab7f73b310a3.es.png) + +En el diagrama anterior, una lectura de humedad del suelo muestra 658. La planta es regada, pero esta lectura no cambia inmediatamente, ya que el agua aún no ha llegado al sensor. Incluso el riego puede terminar antes de que el agua alcance el sensor y el valor baje para reflejar el nuevo nivel de humedad. + +Si estuvieras escribiendo código para controlar un sistema de riego mediante un relé basado en los niveles de humedad del suelo, tendrías que tener en cuenta este retraso y construir un sistema de temporización más inteligente en tu dispositivo IoT. + +✅ Tómate un momento para pensar cómo podrías hacer esto. + +### Controlar la temporización del sensor y el actuador + +Imagina que te han encargado construir un sistema de riego para una granja. Según el tipo de suelo, se ha determinado que el nivel ideal de humedad del suelo para las plantas corresponde a una lectura de voltaje analógico de 400-450. + +Podrías programar el dispositivo de la misma manera que una luz nocturna: todo el tiempo que el sensor lea por encima de 450, encender un relé para activar una bomba. El problema es que el agua tarda un tiempo en llegar desde la bomba, atravesar el suelo y alcanzar el sensor. El sensor detendrá el agua cuando detecte un nivel de 450, pero el nivel de agua seguirá bajando mientras el agua bombeada sigue empapando el suelo. El resultado final es agua desperdiciada y el riesgo de dañar las raíces. + +✅ Recuerda: demasiada agua puede ser tan perjudicial para las plantas como muy poca, y desperdicia un recurso valioso. + +La mejor solución es entender que hay un retraso entre el momento en que el actuador se activa y el cambio en la propiedad que el sensor mide. Esto significa que no solo el sensor debe esperar un tiempo antes de medir el valor nuevamente, sino que el actuador debe apagarse por un tiempo antes de que se realice la siguiente medición del sensor. + +¿Cuánto tiempo debe estar encendido el relé cada vez? Es mejor pecar de precavido y encender el relé solo por un corto tiempo, luego esperar a que el agua empape el suelo y volver a verificar los niveles de humedad. Después de todo, siempre puedes encenderlo nuevamente para agregar más agua, pero no puedes quitar agua del suelo. + +> 💁 Este tipo de control de temporización es muy específico para el dispositivo IoT que estás construyendo, la propiedad que estás midiendo y los sensores y actuadores utilizados. + +![Una planta de fresa conectada al agua mediante una bomba, con la bomba conectada a un relé. El relé y un sensor de humedad del suelo en la planta están conectados a un Raspberry Pi](../../../../../translated_images/strawberry-with-pump.b410fc72ac6aabad3e28de9775bf2393ead73dcfec6fd8c9bc01cf107ecd171a.es.png) + +Por ejemplo, tengo una planta de fresa con un sensor de humedad del suelo y una bomba controlada por un relé. He observado que cuando agrego agua, tarda unos 20 segundos en estabilizarse la lectura de humedad del suelo. Esto significa que necesito apagar el relé y esperar 20 segundos antes de verificar los niveles de humedad. Prefiero tener poca agua que demasiada: siempre puedo encender la bomba nuevamente, pero no puedo quitar agua de la planta. + +![Paso 1, tomar medición. Paso 2, agregar agua. Paso 3, esperar a que el agua empape el suelo. Paso 4, volver a tomar medición](../../../../../translated_images/soil-moisture-delay.865f3fae206db01d5f8f100f4f44040215d44a0412dd3450aef7ff7b93b6d273.es.png) + +Esto significa que el mejor proceso sería un ciclo de riego que sea algo como: + +* Encender la bomba durante 5 segundos +* Esperar 20 segundos +* Verificar la humedad del suelo +* Si el nivel sigue siendo superior al necesario, repetir los pasos anteriores + +5 segundos podrían ser demasiado tiempo para la bomba, especialmente si los niveles de humedad están solo ligeramente por encima del nivel requerido. La mejor manera de saber qué temporización usar es probarla y luego ajustarla cuando tengas datos del sensor, con un bucle de retroalimentación constante. Esto incluso puede llevar a una temporización más granular, como encender la bomba durante 1 segundo por cada 100 por encima del nivel de humedad requerido, en lugar de un tiempo fijo de 5 segundos. + +✅ Investiga: ¿Existen otras consideraciones de temporización? ¿Se puede regar la planta en cualquier momento que la humedad del suelo sea demasiado baja, o hay momentos específicos del día que son buenos y malos para regar las plantas? + +> 💁 Las predicciones meteorológicas también pueden tomarse en cuenta al controlar sistemas de riego automatizados para cultivos al aire libre. Si se espera lluvia, entonces el riego puede posponerse hasta después de que termine la lluvia. En ese momento, el suelo podría estar lo suficientemente húmedo como para no necesitar riego, mucho más eficiente que desperdiciar agua regando justo antes de la lluvia. + +## Agregar temporización a tu servidor de control de plantas + +El código del servidor puede modificarse para agregar control alrededor de la temporización del ciclo de riego y esperar a que los niveles de humedad del suelo cambien. La lógica del servidor para controlar la temporización del relé es: + +1. Mensaje de telemetría recibido +1. Verificar el nivel de humedad del suelo +1. Si está bien, no hacer nada. Si la lectura es demasiado alta (lo que significa que la humedad del suelo es demasiado baja), entonces: + 1. Enviar un comando para encender el relé + 1. Esperar 5 segundos + 1. Enviar un comando para apagar el relé + 1. Esperar 20 segundos para que los niveles de humedad del suelo se estabilicen + +El ciclo de riego, el proceso desde recibir el mensaje de telemetría hasta estar listo para procesar nuevamente los niveles de humedad del suelo, toma aproximadamente 25 segundos. Estamos enviando niveles de humedad del suelo cada 10 segundos, por lo que hay un solapamiento donde se recibe un mensaje mientras el servidor está esperando que los niveles de humedad del suelo se estabilicen, lo que podría iniciar otro ciclo de riego. + +Hay dos opciones para solucionar esto: + +* Cambiar el código del dispositivo IoT para enviar telemetría solo cada minuto, de esta manera el ciclo de riego se completará antes de que se envíe el siguiente mensaje +* Cancelar la suscripción a la telemetría durante el ciclo de riego + +La primera opción no siempre es una buena solución para grandes granjas. El agricultor podría querer capturar los niveles de humedad del suelo mientras se está regando para un análisis posterior, por ejemplo, para estar al tanto del flujo de agua en diferentes áreas de la granja y guiar un riego más específico. La segunda opción es mejor: el código simplemente ignora la telemetría cuando no puede usarla, pero la telemetría sigue estando disponible para otros servicios que puedan suscribirse a ella. + +> 💁 Los datos de IoT no se envían desde un solo dispositivo a un solo servicio, en cambio, muchos dispositivos pueden enviar datos a un broker, y muchos servicios pueden escuchar los datos del broker. Por ejemplo, un servicio podría escuchar los datos de humedad del suelo y almacenarlos en una base de datos para análisis posterior. Otro servicio también puede escuchar la misma telemetría para controlar un sistema de riego. + +### Tarea - agregar temporización a tu servidor de control de plantas + +Actualiza tu código de servidor para ejecutar el relé durante 5 segundos y luego esperar 20 segundos. + +1. Abre la carpeta `soil-moisture-sensor-server` en VS Code si aún no está abierta. Asegúrate de que el entorno virtual esté activado. + +1. Abre el archivo `app.py` + +1. Agrega el siguiente código al archivo `app.py` debajo de las importaciones existentes: + + ```python + import threading + ``` + + Esta declaración importa `threading` de las bibliotecas de Python. Threading permite que Python ejecute otro código mientras espera. + +1. Agrega el siguiente código antes de la función `handle_telemetry` que maneja los mensajes de telemetría recibidos por el código del servidor: + + ```python + water_time = 5 + wait_time = 20 + ``` + + Esto define cuánto tiempo ejecutar el relé (`water_time`) y cuánto tiempo esperar después para verificar la humedad del suelo (`wait_time`). + +1. Debajo de este código, agrega lo siguiente: + + ```python + def send_relay_command(client, state): + command = { 'relay_on' : state } + print("Sending message:", command) + client.publish(server_command_topic, json.dumps(command)) + ``` + + Este código define una función llamada `send_relay_command` que envía un comando a través de MQTT para controlar el relé. La telemetría se crea como un diccionario y luego se convierte en una cadena JSON. El valor pasado en `state` determina si el relé debe estar encendido o apagado. + +1. Después de la función `send_relay_code`, agrega el siguiente código: + + ```python + def control_relay(client): + print("Unsubscribing from telemetry") + mqtt_client.unsubscribe(client_telemetry_topic) + + send_relay_command(client, True) + time.sleep(water_time) + send_relay_command(client, False) + + time.sleep(wait_time) + + print("Subscribing to telemetry") + mqtt_client.subscribe(client_telemetry_topic) + ``` + + Esto define una función para controlar el relé según la temporización requerida. Comienza cancelando la suscripción a la telemetría para que los mensajes de humedad del suelo no se procesen mientras se realiza el riego. Luego envía un comando para encender el relé. Después espera el tiempo definido en `water_time` antes de enviar un comando para apagar el relé. Finalmente, espera que los niveles de humedad del suelo se estabilicen durante el tiempo definido en `wait_time`. Luego vuelve a suscribirse a la telemetría. + +1. Cambia la función `handle_telemetry` por la siguiente: + + ```python + def handle_telemetry(client, userdata, message): + payload = json.loads(message.payload.decode()) + print("Message received:", payload) + + if payload['soil_moisture'] > 450: + threading.Thread(target=control_relay, args=(client,)).start() + ``` + + Este código verifica el nivel de humedad del suelo. Si es mayor que 450, el suelo necesita riego, por lo que llama a la función `control_relay`. Esta función se ejecuta en un hilo separado, funcionando en segundo plano. + +1. Asegúrate de que tu dispositivo IoT esté funcionando, luego ejecuta este código. Cambia los niveles de humedad del suelo y observa qué sucede con el relé: debería encenderse durante 5 segundos y luego permanecer apagado al menos 20 segundos, encendiéndose solo si los niveles de humedad del suelo no son suficientes. + + ```output + (.venv) ➜ soil-moisture-sensor-server ✗ python app.py + Message received: {'soil_moisture': 457} + Unsubscribing from telemetry + Sending message: {'relay_on': True} + Sending message: {'relay_on': False} + Subscribing to telemetry + Message received: {'soil_moisture': 302} + ``` + + Una buena manera de probar esto en un sistema de riego simulado es usar suelo seco y luego verter agua manualmente mientras el relé está encendido, deteniendo el vertido cuando el relé se apaga. + +> 💁 Puedes encontrar este código en la carpeta [code-timing](../../../../../2-farm/lessons/3-automated-plant-watering/code-timing). + +> 💁 Si deseas usar una bomba para construir un sistema de riego real, puedes usar una [bomba de agua de 6V](https://www.seeedstudio.com/6V-Mini-Water-Pump-p-1945.html) con una [fuente de alimentación USB](https://www.adafruit.com/product/3628). Asegúrate de que la alimentación hacia o desde la bomba esté conectada a través del relé. + +--- + +## 🚀 Desafío + +¿Puedes pensar en otros dispositivos IoT o eléctricos que tengan un problema similar donde los resultados del actuador tardan en llegar al sensor? Probablemente tengas algunos en tu casa o escuela. + +* ¿Qué propiedades miden? +* ¿Cuánto tiempo tarda en cambiar la propiedad después de que se usa un actuador? +* ¿Está bien que la propiedad cambie más allá del valor requerido? +* ¿Cómo puede volver al valor requerido si es necesario? + +## Cuestionario posterior a la clase + +[Cuestionario posterior a la clase](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/14) + +## Revisión y autoestudio + +* Lee más sobre relés, incluyendo su uso histórico en centrales telefónicas, en la [página de Wikipedia sobre relés](https://wikipedia.org/wiki/Relay). + +## Asignación + +[Construir un ciclo de riego más eficiente](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/3-automated-plant-watering/assignment.md b/translations/es/2-farm/lessons/3-automated-plant-watering/assignment.md new file mode 100644 index 00000000..66fd7193 --- /dev/null +++ b/translations/es/2-farm/lessons/3-automated-plant-watering/assignment.md @@ -0,0 +1,54 @@ + +# Construye un ciclo de riego más eficiente + +## Instrucciones + +Esta lección cubrió cómo controlar un relé mediante datos de sensores, y ese relé podría, a su vez, controlar una bomba para un sistema de riego. Para un volumen definido de suelo, hacer funcionar una bomba durante un tiempo fijo debería tener siempre el mismo impacto en la humedad del suelo. Esto significa que puedes tener una idea de cuántos segundos de riego corresponden a una cierta disminución en la lectura de humedad del suelo. Usando estos datos, puedes construir un sistema de riego más controlado. + +Para esta tarea, calcularás cuánto tiempo debe funcionar la bomba para lograr un aumento particular en la humedad del suelo. + +> ⚠️ Si estás utilizando hardware IoT virtual, puedes seguir este proceso, pero simula los resultados aumentando manualmente la lectura de humedad del suelo por una cantidad fija por segundo mientras el relé está encendido. + +1. Comienza con suelo seco. Mide la humedad del suelo. + +1. Agrega una cantidad fija de agua, ya sea haciendo funcionar la bomba durante 1 segundo o vertiendo una cantidad fija de agua. + + > La bomba siempre debe funcionar a una velocidad constante, por lo que cada segundo que funcione debe suministrar la misma cantidad de agua. + +1. Espera hasta que el nivel de humedad del suelo se estabilice y toma una lectura. + +1. Repite esto varias veces y crea una tabla con los resultados. Un ejemplo de esta tabla se muestra a continuación. + + | Tiempo total de la bomba | Humedad del suelo | Disminución | + | --- | --: | -: | + | Seco | 643 | 0 | + | 1s | 621 | 22 | + | 2s | 601 | 20 | + | 3s | 579 | 22 | + | 4s | 560 | 19 | + | 5s | 539 | 21 | + | 6s | 521 | 18 | + +1. Calcula un aumento promedio en la humedad del suelo por segundo de agua. En el ejemplo anterior, cada segundo de agua disminuye la lectura en un promedio de 20.3. + +1. Usa estos datos para mejorar la eficiencia de tu código del servidor, haciendo funcionar la bomba durante el tiempo necesario para llevar la humedad del suelo al nivel deseado. + +## Rúbrica + +| Criterios | Ejemplar | Adecuado | Necesita Mejorar | +| --------- | -------- | -------- | ---------------- | +| Captura de datos de humedad del suelo | Es capaz de capturar múltiples lecturas después de agregar cantidades fijas de agua | Es capaz de capturar algunas lecturas con cantidades fijas de agua | Solo puede capturar una o dos lecturas, o no puede usar cantidades fijas de agua | +| Calibración del código del servidor | Es capaz de calcular una disminución promedio en la lectura de humedad del suelo y actualizar el código del servidor para usar este valor | Es capaz de calcular una disminución promedio, pero no puede actualizar el código del servidor, o no puede calcular correctamente un promedio, pero usa este valor para actualizar correctamente el código del servidor | No es capaz de calcular un promedio ni de actualizar el código del servidor | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/3-automated-plant-watering/pi-relay.md b/translations/es/2-farm/lessons/3-automated-plant-watering/pi-relay.md new file mode 100644 index 00000000..e4d5a8f7 --- /dev/null +++ b/translations/es/2-farm/lessons/3-automated-plant-watering/pi-relay.md @@ -0,0 +1,123 @@ + +# Controlar un relé - Raspberry Pi + +En esta parte de la lección, agregarás un relé a tu Raspberry Pi además del sensor de humedad del suelo, y lo controlarás en función del nivel de humedad del suelo. + +## Hardware + +La Raspberry Pi necesita un relé. + +El relé que usarás es un [Grove relay](https://www.seeedstudio.com/Grove-Relay.html), un relé normalmente abierto (lo que significa que el circuito de salida está abierto o desconectado cuando no se envía señal al relé) que puede manejar circuitos de salida de hasta 250V y 10A. + +Este es un actuador digital, por lo que se conecta a un pin digital en el Grove Base Hat. + +### Conectar el relé + +El relé Grove puede conectarse a la Raspberry Pi. + +#### Tarea + +Conecta el relé. + +![Un relé Grove](../../../../../translated_images/grove-relay.d426958ca210fbd0fb7983d7edc069d46c73a8b0a099d94797bd756f7b6bb6be.es.png) + +1. Inserta un extremo de un cable Grove en el conector del relé. Solo encajará de una manera. + +1. Con la Raspberry Pi apagada, conecta el otro extremo del cable Grove al conector digital marcado como **D5** en el Grove Base Hat conectado a la Pi. Este conector es el segundo desde la izquierda, en la fila de conectores junto a los pines GPIO. Deja el sensor de humedad del suelo conectado al conector **A0**. + +![El relé Grove conectado al conector D5, y el sensor de humedad del suelo conectado al conector A0](../../../../../translated_images/pi-relay-and-soil-moisture-sensor.02f3198975b8c53e69ec716cd2719ce117700bd1fc933eaf93476c103c57939b.es.png) + +1. Inserta el sensor de humedad del suelo en la tierra, si no lo has hecho ya en la lección anterior. + +## Programar el relé + +La Raspberry Pi ahora puede ser programada para usar el relé conectado. + +### Tarea + +Programa el dispositivo. + +1. Enciende la Pi y espera a que arranque. + +1. Abre el proyecto `soil-moisture-sensor` de la lección anterior en VS Code si no está ya abierto. Estarás agregando a este proyecto. + +1. Añade el siguiente código al archivo `app.py` debajo de las importaciones existentes: + + ```python + from grove.grove_relay import GroveRelay + ``` + + Esta declaración importa el `GroveRelay` de las bibliotecas de Python Grove para interactuar con el relé Grove. + +1. Añade el siguiente código debajo de la declaración de la clase `ADC` para crear una instancia de `GroveRelay`: + + ```python + relay = GroveRelay(5) + ``` + + Esto crea un relé usando el pin **D5**, el pin digital al que conectaste el relé. + +1. Para probar que el relé funciona, añade lo siguiente al bucle `while True:`: + + ```python + relay.on() + time.sleep(.5) + relay.off() + ``` + + El código enciende el relé, espera 0.5 segundos, luego apaga el relé. + +1. Ejecuta la aplicación de Python. El relé se encenderá y apagará cada 10 segundos, con un retraso de medio segundo entre encender y apagar. Escucharás el clic del relé al encenderse y apagarse. Un LED en la placa Grove se encenderá cuando el relé esté encendido y se apagará cuando el relé esté apagado. + + ![El relé encendiéndose y apagándose](../../../../../images/relay-turn-on-off.gif) + +## Controlar el relé según la humedad del suelo + +Ahora que el relé funciona, puede ser controlado en respuesta a las lecturas de humedad del suelo. + +### Tarea + +Controla el relé. + +1. Elimina las 3 líneas de código que agregaste para probar el relé. Reemplázalas con el siguiente código: + + ```python + if soil_moisture > 450: + print("Soil Moisture is too low, turning relay on.") + relay.on() + else: + print("Soil Moisture is ok, turning relay off.") + relay.off() + ``` + + Este código verifica el nivel de humedad del suelo desde el sensor de humedad del suelo. Si está por encima de 450, enciende el relé, y lo apaga cuando baja de 450. + + > 💁 Recuerda que el sensor capacitivo de humedad del suelo lee que cuanto más bajo es el nivel de humedad del suelo, más humedad hay en la tierra y viceversa. + +1. Ejecuta la aplicación de Python. Verás que el relé se enciende o apaga dependiendo del nivel de humedad del suelo. Prueba en tierra seca, luego añade agua. + + ```output + Soil Moisture: 638 + Soil Moisture is too low, turning relay on. + Soil Moisture: 452 + Soil Moisture is too low, turning relay on. + Soil Moisture: 347 + Soil Moisture is ok, turning relay off. + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-relay/pi](../../../../../2-farm/lessons/3-automated-plant-watering/code-relay/pi). + +😀 ¡Tu programa para controlar un relé con el sensor de humedad del suelo fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/3-automated-plant-watering/virtual-device-relay.md b/translations/es/2-farm/lessons/3-automated-plant-watering/virtual-device-relay.md new file mode 100644 index 00000000..85cbccae --- /dev/null +++ b/translations/es/2-farm/lessons/3-automated-plant-watering/virtual-device-relay.md @@ -0,0 +1,127 @@ + +# Controlar un relé - Hardware IoT Virtual + +En esta parte de la lección, agregarás un relé a tu dispositivo IoT virtual además del sensor de humedad del suelo, y lo controlarás en función del nivel de humedad del suelo. + +## Hardware Virtual + +El dispositivo IoT virtual usará un relé simulado de Grove. Esto mantiene este laboratorio igual que usar un Raspberry Pi con un relé físico de Grove. + +En un dispositivo IoT físico, el relé sería un relé normalmente abierto (lo que significa que el circuito de salida está abierto o desconectado cuando no se envía señal al relé). Un relé como este puede manejar circuitos de salida de hasta 250V y 10A. + +### Agregar el relé a CounterFit + +Para usar un relé virtual, necesitas agregarlo a la aplicación CounterFit. + +#### Tarea + +Agrega el relé a la aplicación CounterFit. + +1. Abre el proyecto `soil-moisture-sensor` de la lección anterior en VS Code si no está ya abierto. Estarás agregando a este proyecto. + +1. Asegúrate de que la aplicación web de CounterFit esté en ejecución. + +1. Crea un relé: + + 1. En el cuadro *Create actuator* en el panel *Actuators*, despliega el cuadro *Actuator type* y selecciona *Relay*. + + 1. Configura el *Pin* en *5*. + + 1. Selecciona el botón **Add** para crear el relé en el Pin 5. + + ![Configuración del relé](../../../../../translated_images/counterfit-create-relay.fa7c40fd0f2f6afc33b35ea94fcb235085be4861e14e3fe6b9b7bcfc82d1c888.es.png) + + El relé será creado y aparecerá en la lista de actuadores. + + ![Relé creado](../../../../../translated_images/counterfit-relay.bbf74c1dbdc8b9acd983367fcbd06703a402aefef6af54ddb28e11307ba8a12c.es.png) + +## Programar el relé + +La aplicación del sensor de humedad del suelo ahora puede ser programada para usar el relé virtual. + +### Tarea + +Programa el dispositivo virtual. + +1. Abre el proyecto `soil-moisture-sensor` de la lección anterior en VS Code si no está ya abierto. Estarás agregando a este proyecto. + +1. Agrega el siguiente código al archivo `app.py` debajo de las importaciones existentes: + + ```python + from counterfit_shims_grove.grove_relay import GroveRelay + ``` + + Esta declaración importa el `GroveRelay` de las bibliotecas shim de Grove para interactuar con el relé virtual de Grove. + +1. Agrega el siguiente código debajo de la declaración de la clase `ADC` para crear una instancia de `GroveRelay`: + + ```python + relay = GroveRelay(5) + ``` + + Esto crea un relé usando el pin **5**, el pin al que conectaste el relé. + +1. Para probar que el relé funciona, agrega lo siguiente al bucle `while True:`: + + ```python + relay.on() + time.sleep(.5) + relay.off() + ``` + + El código enciende el relé, espera 0.5 segundos y luego lo apaga. + +1. Ejecuta la aplicación de Python. El relé se encenderá y apagará cada 10 segundos, con un retraso de medio segundo entre encenderse y apagarse. Verás el relé virtual en la aplicación CounterFit cerrarse y abrirse a medida que el relé se enciende y apaga. + + ![El relé virtual encendiéndose y apagándose](../../../../../images/virtual-relay-turn-on-off.gif) + +## Controlar el relé según la humedad del suelo + +Ahora que el relé funciona, puede ser controlado en respuesta a las lecturas de humedad del suelo. + +### Tarea + +Controla el relé. + +1. Elimina las 3 líneas de código que agregaste para probar el relé. Reemplázalas con el siguiente código en su lugar: + + ```python + if soil_moisture > 450: + print("Soil Moisture is too low, turning relay on.") + relay.on() + else: + print("Soil Moisture is ok, turning relay off.") + relay.off() + ``` + + Este código verifica el nivel de humedad del suelo desde el sensor de humedad del suelo. Si está por encima de 450, enciende el relé, apagándolo si baja de 450. + + > 💁 Recuerda que el sensor capacitivo de humedad del suelo lee que cuanto más bajo es el nivel de humedad del suelo, más humedad hay en el suelo y viceversa. + +1. Ejecuta la aplicación de Python. Verás que el relé se enciende o apaga dependiendo de los niveles de humedad del suelo. Cambia el *Value* o la configuración de *Random* del sensor de humedad del suelo para ver cómo cambia el valor. + + ```output + Soil Moisture: 638 + Soil Moisture is too low, turning relay on. + Soil Moisture: 452 + Soil Moisture is too low, turning relay on. + Soil Moisture: 347 + Soil Moisture is ok, turning relay off. + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-relay/virtual-device](../../../../../2-farm/lessons/3-automated-plant-watering/code-relay/virtual-device). + +😀 ¡Tu programa de sensor de humedad del suelo virtual controlando un relé fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/3-automated-plant-watering/wio-terminal-relay.md b/translations/es/2-farm/lessons/3-automated-plant-watering/wio-terminal-relay.md new file mode 100644 index 00000000..8601a844 --- /dev/null +++ b/translations/es/2-farm/lessons/3-automated-plant-watering/wio-terminal-relay.md @@ -0,0 +1,121 @@ + +# Controlar un relé - Wio Terminal + +En esta parte de la lección, agregarás un relé a tu Wio Terminal además del sensor de humedad del suelo, y lo controlarás en función del nivel de humedad del suelo. + +## Hardware + +El Wio Terminal necesita un relé. + +El relé que usarás es un [Grove relay](https://www.seeedstudio.com/Grove-Relay.html), un relé normalmente abierto (lo que significa que el circuito de salida está abierto o desconectado cuando no se envía señal al relé) que puede manejar circuitos de salida de hasta 250V y 10A. + +Este es un actuador digital, por lo que se conecta a los pines digitales del Wio Terminal. El puerto combinado analógico/digital ya está en uso con el sensor de humedad del suelo, así que este se conecta al otro puerto, que es un puerto combinado I2C y digital. + +### Conectar el relé + +El relé Grove puede conectarse al puerto digital del Wio Terminal. + +#### Tarea + +Conecta el relé. + +![Un relé Grove](../../../../../translated_images/grove-relay.d426958ca210fbd0fb7983d7edc069d46c73a8b0a099d94797bd756f7b6bb6be.es.png) + +1. Inserta un extremo de un cable Grove en el conector del relé. Solo encajará de una manera. + +1. Con el Wio Terminal desconectado de tu computadora u otra fuente de alimentación, conecta el otro extremo del cable Grove al conector Grove del lado izquierdo del Wio Terminal, mirando la pantalla. Deja el sensor de humedad del suelo conectado al conector del lado derecho. + +![El relé Grove conectado al conector izquierdo, y el sensor de humedad del suelo conectado al conector derecho](../../../../../translated_images/wio-relay-and-soil-moisture-sensor.ed722202d42babe0be5f4518cf13e8c2c81e8df21d37839266cbdb60cf30172d.es.png) + +1. Inserta el sensor de humedad del suelo en la tierra, si no lo has hecho ya en la lección anterior. + +## Programar el relé + +El Wio Terminal ahora puede ser programado para usar el relé conectado. + +### Tarea + +Programa el dispositivo. + +1. Abre el proyecto `soil-moisture-sensor` de la lección anterior en VS Code si no está ya abierto. Vas a agregar código a este proyecto. + +2. No hay una biblioteca para este actuador: es un actuador digital controlado por una señal alta o baja. Para encenderlo, envías una señal alta al pin (3.3V), y para apagarlo envías una señal baja (0V). Puedes hacerlo usando la función [`digitalWrite`](https://www.arduino.cc/reference/en/language/functions/digital-io/digitalwrite/) incorporada en Arduino. Comienza agregando lo siguiente al final de la función `setup` para configurar el puerto combinado I2C/digital como un pin de salida para enviar voltaje al relé: + + ```cpp + pinMode(PIN_WIRE_SCL, OUTPUT); + ``` + + `PIN_WIRE_SCL` es el número de puerto para el puerto combinado I2C/digital. + +1. Para probar que el relé funciona, agrega lo siguiente a la función `loop`, debajo del último `delay`: + + ```cpp + digitalWrite(PIN_WIRE_SCL, HIGH); + delay(500); + digitalWrite(PIN_WIRE_SCL, LOW); + ``` + + El código envía una señal alta al pin al que está conectado el relé para encenderlo, espera 500ms (medio segundo), y luego envía una señal baja para apagar el relé. + +1. Compila y sube el código al Wio Terminal. + +1. Una vez subido, el relé se encenderá y apagará cada 10 segundos, con un retraso de medio segundo entre encenderse y apagarse. Escucharás el clic del relé al encenderse y apagarse. Un LED en la placa Grove se iluminará cuando el relé esté encendido y se apagará cuando el relé esté apagado. + + ![El relé encendiéndose y apagándose](../../../../../images/relay-turn-on-off.gif) + +## Controlar el relé según la humedad del suelo + +Ahora que el relé funciona, puede ser controlado en respuesta a las lecturas de humedad del suelo. + +### Tarea + +Controla el relé. + +1. Elimina las 3 líneas de código que agregaste para probar el relé. Reemplázalas con el siguiente código: + + ```cpp + if (soil_moisture > 450) + { + Serial.println("Soil Moisture is too low, turning relay on."); + digitalWrite(PIN_WIRE_SCL, HIGH); + } + else + { + Serial.println("Soil Moisture is ok, turning relay off."); + digitalWrite(PIN_WIRE_SCL, LOW); + } + ``` + + Este código verifica el nivel de humedad del suelo desde el sensor de humedad del suelo. Si está por encima de 450, enciende el relé, y lo apaga cuando baja de 450. + + > 💁 Recuerda que el sensor capacitivo de humedad del suelo lee que cuanto más bajo es el nivel de humedad del suelo, más humedad hay en la tierra, y viceversa. + +1. Compila y sube el código al Wio Terminal. + +1. Monitorea el dispositivo a través del monitor serial. Verás que el relé se enciende o apaga dependiendo del nivel de humedad del suelo. Prueba en tierra seca y luego agrega agua. + + ```output + Soil Moisture: 638 + Soil Moisture is too low, turning relay on. + Soil Moisture: 452 + Soil Moisture is too low, turning relay on. + Soil Moisture: 347 + Soil Moisture is ok, turning relay off. + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-relay/wio-terminal](../../../../../2-farm/lessons/3-automated-plant-watering/code-relay/wio-terminal). + +😀 ¡Tu programa para controlar un relé con el sensor de humedad del suelo fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/README.md b/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/README.md new file mode 100644 index 00000000..ff7a5ea4 --- /dev/null +++ b/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/README.md @@ -0,0 +1,451 @@ + +# Migra tu planta a la nube + +![Un resumen visual de esta lección](../../../../../translated_images/lesson-8.3f21f3c11159e6a0a376351973ea5724d5de68fa23b4288853a174bed9ac48c3.es.jpg) + +> Resumen visual por [Nitya Narasimhan](https://github.com/nitya). Haz clic en la imagen para una versión más grande. + +Esta lección fue impartida como parte de la [serie de Agricultura Digital del Proyecto 2 de IoT para Principiantes](https://youtube.com/playlist?list=PLmsFUfdnGr3yCutmcVg6eAUEfsGiFXgcx) del [Microsoft Reactor](https://developer.microsoft.com/reactor/?WT.mc_id=academic-17441-jabenn). + +[![Conecta tu dispositivo a la nube con Azure IoT Hub](https://img.youtube.com/vi/bNxjopXkhvk/0.jpg)](https://youtu.be/bNxjopXkhvk) + +## Cuestionario previo a la lección + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/15) + +## Introducción + +En la lección anterior, aprendiste a conectar tu planta a un broker MQTT y a controlar un relé desde un código de servidor que se ejecuta localmente. Esto constituye el núcleo de un sistema automatizado de riego conectado a internet, que puede usarse tanto para plantas individuales en casa como para granjas comerciales. + +El dispositivo IoT se comunicaba con un broker MQTT público como una forma de demostrar los principios básicos, pero esta no es la manera más confiable ni segura. En esta lección, aprenderás sobre la nube y las capacidades de IoT que ofrecen los servicios públicos en la nube. También aprenderás cómo migrar tu planta de un broker MQTT público a uno de estos servicios en la nube. + +En esta lección cubriremos: + +* [¿Qué es la nube?](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud) +* [Crear una suscripción en la nube](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud) +* [Servicios de IoT en la nube](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud) +* [Crear un servicio IoT en la nube](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud) +* [Comunicarte con IoT Hub](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud) +* [Conectar tu dispositivo al servicio IoT](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud) + +## ¿Qué es la nube? + +Antes de la nube, cuando una empresa quería proporcionar servicios a sus empleados (como bases de datos o almacenamiento de archivos) o al público (como sitios web), construía y operaba un centro de datos. Esto podía ir desde una sala con unos pocos ordenadores hasta un edificio con muchos. La empresa se encargaba de todo, incluyendo: + +* Comprar ordenadores +* Mantenimiento del hardware +* Energía y refrigeración +* Redes +* Seguridad, tanto del edificio como del software en los ordenadores +* Instalación y actualización de software + +Esto podía ser muy costoso, requerir una amplia gama de empleados especializados y ser muy lento para adaptarse a cambios. Por ejemplo, si una tienda en línea necesitaba prepararse para una temporada alta de ventas, tendría que planificar con meses de antelación para comprar más hardware, configurarlo, instalarlo e implementar el software necesario para gestionar las ventas. Después de la temporada alta, cuando las ventas disminuyeran, se quedarían con ordenadores que ya habían pagado pero que estarían inactivos hasta la próxima temporada. + +✅ ¿Crees que esto permitiría a las empresas moverse rápidamente? Si una tienda de ropa en línea se volviera popular de repente porque una celebridad fue vista usando su ropa, ¿podrían aumentar su capacidad de cómputo lo suficientemente rápido para manejar el repentino aumento de pedidos? + +### El ordenador de otra persona + +La nube a menudo se describe en broma como "el ordenador de otra persona". La idea inicial era simple: en lugar de comprar ordenadores, alquilas los de otra persona. Un proveedor de computación en la nube se encargaría de gestionar enormes centros de datos. Ellos serían responsables de comprar e instalar el hardware, gestionar la energía y la refrigeración, las redes, la seguridad del edificio, las actualizaciones de hardware y software, todo. Como cliente, alquilas los ordenadores que necesitas, aumentando el alquiler cuando la demanda sube y reduciéndolo cuando la demanda baja. Estos centros de datos en la nube están distribuidos por todo el mundo. + +![Un centro de datos en la nube de Microsoft](../../../../../translated_images/azure-region-existing.73f704604f2aa6cb9b5a49ed40e93d4fd81ae3f4e6af4a8ca504023902832f56.es.png) +![Expansión planificada de un centro de datos en la nube de Microsoft](../../../../../translated_images/azure-region-planned-expansion.a5074a1e8af74f156a73552d502429e5b126ea5019274d767ecb4b9afdad442b.es.png) + +Estos centros de datos pueden tener varios kilómetros cuadrados de tamaño. Las imágenes anteriores fueron tomadas hace algunos años en un centro de datos en la nube de Microsoft y muestran el tamaño inicial, junto con una expansión planificada. El área despejada para la expansión tiene más de 5 kilómetros cuadrados. + +> 💁 Estos centros de datos requieren cantidades tan grandes de energía que algunos tienen sus propias estaciones de energía. Debido a su tamaño y al nivel de inversión de los proveedores de la nube, suelen ser muy respetuosos con el medio ambiente. Son más eficientes que un gran número de pequeños centros de datos, funcionan principalmente con energía renovable y los proveedores de la nube trabajan arduamente para reducir los desechos, disminuir el uso de agua y reforestar las áreas taladas para construir los centros de datos. Puedes leer más sobre cómo un proveedor de la nube está trabajando en sostenibilidad en el [sitio de sostenibilidad de Azure](https://azure.microsoft.com/global-infrastructure/sustainability/?WT.mc_id=academic-17441-jabenn). + +✅ Investiga: Lee sobre las principales nubes como [Azure de Microsoft](https://azure.microsoft.com/?WT.mc_id=academic-17441-jabenn) o [GCP de Google](https://cloud.google.com). ¿Cuántos centros de datos tienen y dónde están ubicados en el mundo? + +Usar la nube reduce los costos para las empresas y les permite centrarse en lo que hacen mejor, dejando la experiencia en computación en la nube en manos del proveedor. Las empresas ya no necesitan alquilar o comprar espacio en centros de datos, pagar a diferentes proveedores por conectividad y energía, o emplear expertos. En su lugar, pueden pagar una factura mensual al proveedor de la nube para que se encargue de todo. + +El proveedor de la nube puede entonces aprovechar las economías de escala para reducir costos, comprando ordenadores al por mayor a precios más bajos, invirtiendo en herramientas para reducir su carga de trabajo de mantenimiento, e incluso diseñando y construyendo su propio hardware para mejorar su oferta en la nube. + +### Microsoft Azure + +Azure es la nube para desarrolladores de Microsoft, y es la nube que usarás en estas lecciones. El siguiente video ofrece una breve descripción de Azure: + +[![Video de introducción a Azure](../../../../../translated_images/what-is-azure-video-thumbnail.20174db09e03bbb87d213f928d3cb27410305d2e567e952827de8478dbda959b.es.png)](https://www.microsoft.com/videoplayer/embed/RE4Ibng?WT.mc_id=academic-17441-jabenn) + +## Crear una suscripción en la nube + +Para usar servicios en la nube, necesitarás registrarte para obtener una suscripción con un proveedor de nube. En esta lección, te registrarás para obtener una suscripción de Microsoft Azure. Si ya tienes una suscripción de Azure, puedes omitir esta tarea. Los detalles de la suscripción descritos aquí son correctos al momento de escribir, pero pueden cambiar. + +> 💁 Si estás accediendo a estas lecciones a través de tu escuela, es posible que ya tengas una suscripción de Azure disponible. Consulta con tu profesor. + +Hay dos tipos diferentes de suscripción gratuita de Azure a las que puedes registrarte: + +* **Azure para Estudiantes** - Esta es una suscripción diseñada para estudiantes mayores de 18 años. No necesitas una tarjeta de crédito para registrarte y usas tu correo electrónico escolar para validar que eres estudiante. Al registrarte, obtienes $100 USD para gastar en recursos en la nube, junto con servicios gratuitos, incluyendo una versión gratuita de un servicio IoT. Esto dura 12 meses y puedes renovarlo cada año mientras sigas siendo estudiante. + +* **Suscripción gratuita de Azure** - Esta es una suscripción para cualquier persona que no sea estudiante. Necesitarás una tarjeta de crédito para registrarte, pero tu tarjeta no será cobrada, solo se usa para verificar que eres una persona real, no un bot. Obtienes $200 USD de crédito para usar en los primeros 30 días en cualquier servicio, junto con niveles gratuitos de servicios de Azure. Una vez que tu crédito se haya agotado, tu tarjeta no será cobrada a menos que conviertas tu cuenta a una suscripción de pago por uso. + +> 💁 Microsoft también ofrece una suscripción Azure para Estudiantes Starter para estudiantes menores de 18 años, pero al momento de escribir esto, no admite servicios IoT. + +### Tarea - registrarse para una suscripción gratuita en la nube + +Si eres estudiante mayor de 18 años, puedes registrarte para una suscripción Azure para Estudiantes. Necesitarás validar con un correo electrónico escolar. Puedes hacerlo de dos maneras: + +* Regístrate para un paquete de desarrollador estudiantil de GitHub en [education.github.com/pack](https://education.github.com/pack). Esto te da acceso a una variedad de herramientas y ofertas, incluyendo GitHub y Microsoft Azure. Una vez que te registres para el paquete de desarrollador, puedes activar la oferta de Azure para Estudiantes. + +* Regístrate directamente para una cuenta Azure para Estudiantes en [azure.microsoft.com/free/students](https://azure.microsoft.com/free/students/?WT.mc_id=academic-17441-jabenn). + +> ⚠️ Si tu correo electrónico escolar no es reconocido, abre un [issue en este repositorio](https://github.com/Microsoft/IoT-For-Beginners/issues) y veremos si puede ser agregado a la lista de permitidos de Azure para Estudiantes. + +Si no eres estudiante o no tienes un correo electrónico escolar válido, puedes registrarte para una suscripción gratuita de Azure. + +* Regístrate para una suscripción gratuita de Azure en [azure.microsoft.com/free](https://azure.microsoft.com/free/?WT.mc_id=academic-17441-jabenn) + +## Servicios de IoT en la nube + +El broker MQTT público de prueba que has estado utilizando es una gran herramienta para aprender, pero tiene varias desventajas como herramienta para un entorno comercial: + +* Confiabilidad: es un servicio gratuito sin garantías, y puede ser desactivado en cualquier momento. +* Seguridad: es público, por lo que cualquiera podría escuchar tu telemetría o enviar comandos para controlar tu hardware. +* Rendimiento: está diseñado solo para unos pocos mensajes de prueba, por lo que no soportaría una gran cantidad de mensajes enviados. +* Descubrimiento: no hay forma de saber qué dispositivos están conectados. + +Los servicios de IoT en la nube resuelven estos problemas. Son mantenidos por grandes proveedores de nube que invierten mucho en confiabilidad y están disponibles para solucionar cualquier problema que pueda surgir. Tienen seguridad integrada para evitar que los hackers lean tus datos o envíen comandos maliciosos. También tienen un alto rendimiento, siendo capaces de manejar millones de mensajes cada día, aprovechando la nube para escalar según sea necesario. + +> 💁 Aunque pagas por estas ventajas con una tarifa mensual, la mayoría de los proveedores de nube ofrecen una versión gratuita de su servicio IoT con una cantidad limitada de mensajes por día o dispositivos que pueden conectarse. Esta versión gratuita suele ser más que suficiente para que un desarrollador aprenda sobre el servicio. En esta lección, usarás una versión gratuita. + +Los dispositivos IoT se conectan a un servicio en la nube ya sea utilizando un SDK de dispositivo (una biblioteca que proporciona código para trabajar con las características del servicio) o directamente a través de un protocolo de comunicación como MQTT o HTTP. El SDK de dispositivo suele ser la ruta más fácil, ya que maneja todo por ti, como saber a qué temas publicar o suscribirse y cómo manejar la seguridad. + +![Los dispositivos se conectan a un servicio usando un SDK de dispositivo. El código del servidor también se conecta al servicio a través de un SDK](../../../../../translated_images/iot-service-connectivity.7e873847921a5d6fd60d0ba3a943210194518cee0d4e362476624316443275c3.es.png) + +Tu dispositivo luego se comunica con otras partes de tu aplicación a través de este servicio, de manera similar a cómo enviaste telemetría y recibiste comandos a través de MQTT. Esto generalmente se hace utilizando un SDK de servicio o una biblioteca similar. Los mensajes van desde tu dispositivo al servicio, donde otros componentes de tu aplicación pueden leerlos, y los mensajes pueden enviarse de vuelta a tu dispositivo. + +![Los dispositivos sin una clave secreta válida no pueden conectarse al servicio IoT](../../../../../translated_images/iot-service-allowed-denied-connection.818b0063ac213fb84204a7229303764d9b467ca430fb822b4ac2fca267d56726.es.png) + +Estos servicios implementan seguridad al conocer todos los dispositivos que pueden conectarse y enviar datos, ya sea registrando previamente los dispositivos en el servicio o proporcionando a los dispositivos claves secretas o certificados que pueden usar para registrarse en el servicio la primera vez que se conectan. Los dispositivos desconocidos no pueden conectarse; si lo intentan, el servicio rechaza la conexión e ignora los mensajes enviados por ellos. + +✅ Investiga: ¿Cuál es la desventaja de tener un servicio IoT abierto donde cualquier dispositivo o código pueda conectarse? ¿Puedes encontrar ejemplos específicos de hackers aprovechándose de esto? + +Otros componentes de tu aplicación pueden conectarse al servicio IoT y obtener información sobre todos los dispositivos que están conectados o registrados, y comunicarse con ellos directamente, ya sea de forma masiva o individual. +💁 Los servicios de IoT también implementan capacidades adicionales, y los proveedores de la nube tienen servicios y aplicaciones adicionales que se pueden conectar al servicio. Por ejemplo, si deseas almacenar todos los mensajes de telemetría enviados por todos los dispositivos en una base de datos, generalmente solo se necesitan unos pocos clics en la herramienta de configuración del proveedor de la nube para conectar el servicio a una base de datos y transmitir los datos. +## Crear un servicio IoT en la nube + +Ahora que tienes una suscripción a Azure, puedes registrarte en un servicio IoT. El servicio IoT de Microsoft se llama Azure IoT Hub. + +![El logo de Azure IoT Hub](../../../../../translated_images/azure-iot-hub-logo.28a19de76d0a1932464d858f7558712bcdace3e5ec69c434d482ed7ce41c3a26.es.png) + +El siguiente video ofrece una breve descripción general de Azure IoT Hub: + +[![Video de descripción general de Azure IoT Hub](https://img.youtube.com/vi/smuZaZZXKsU/0.jpg)](https://www.youtube.com/watch?v=smuZaZZXKsU) + +> 🎥 Haz clic en la imagen de arriba para ver el video + +✅ Tómate un momento para investigar y leer la descripción general de IoT Hub en la [documentación de Microsoft IoT Hub](https://docs.microsoft.com/azure/iot-hub/about-iot-hub?WT.mc_id=academic-17441-jabenn). + +Los servicios en la nube disponibles en Azure se pueden configurar a través de un portal web o mediante una interfaz de línea de comandos (CLI). Para esta tarea, usarás la CLI. + +### Tarea - instalar Azure CLI + +Para usar Azure CLI, primero debes instalarla en tu PC o Mac. + +1. Sigue las instrucciones en la [documentación de Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli?WT.mc_id=academic-17441-jabenn) para instalar la CLI. + +1. Azure CLI admite una serie de extensiones que añaden capacidades para gestionar una amplia gama de servicios de Azure. Instala la extensión IoT ejecutando el siguiente comando desde tu línea de comandos o terminal: + + ```sh + az extension add --name azure-iot + ``` + +1. Desde tu línea de comandos o terminal, ejecuta el siguiente comando para iniciar sesión en tu suscripción de Azure desde Azure CLI. + + ```sh + az login + ``` + + Se abrirá una página web en tu navegador predeterminado. Inicia sesión usando la cuenta que utilizaste para registrarte en tu suscripción de Azure. Una vez que hayas iniciado sesión, puedes cerrar la pestaña del navegador. + +1. Si tienes varias suscripciones de Azure, como una proporcionada por tu escuela y tu propia suscripción de Azure para Estudiantes, necesitarás seleccionar la que deseas usar. Ejecuta el siguiente comando para listar todas las suscripciones a las que tienes acceso: + + ```sh + az account list --output table + ``` + + En la salida, verás el nombre de cada suscripción junto con su `SubscriptionId`. + + ```output + ➜ ~ az account list --output table + Name CloudName SubscriptionId State IsDefault + ---------------------- ----------- ------------------------------------ ------- ----------- + School-subscription AzureCloud cb30cde9-814a-42f0-a111-754cb788e4e1 Enabled True + Azure for Students AzureCloud fa51c31b-162c-4599-add6-781def2e1fbf Enabled False + ``` + + Para seleccionar la suscripción que deseas usar, utiliza el siguiente comando: + + ```sh + az account set --subscription + ``` + + Sustituye `` por el Id de la suscripción que deseas usar. Después de ejecutar este comando, vuelve a ejecutar el comando para listar tus cuentas. Verás que la columna `IsDefault` estará marcada como `True` para la suscripción que acabas de configurar. + +### Tarea - crear un grupo de recursos + +Los servicios de Azure, como las instancias de IoT Hub, máquinas virtuales, bases de datos o servicios de IA, se denominan **recursos**. Cada recurso debe estar dentro de un **Grupo de Recursos**, que es una agrupación lógica de uno o más recursos. + +> 💁 Usar grupos de recursos significa que puedes gestionar múltiples servicios a la vez. Por ejemplo, una vez que hayas terminado todas las lecciones de este proyecto, puedes eliminar el grupo de recursos, y todos los recursos en él se eliminarán automáticamente. + +1. Hay múltiples centros de datos de Azure en todo el mundo, divididos en regiones. Cuando creas un recurso o grupo de recursos en Azure, debes especificar dónde deseas que se cree. Ejecuta el siguiente comando para obtener la lista de ubicaciones: + + ```sh + az account list-locations --output table + ``` + + Verás una lista de ubicaciones. Esta lista será larga. + + > 💁 En el momento de escribir esto, hay 65 ubicaciones disponibles para desplegar. + + ```output + ➜ ~ az account list-locations --output table + DisplayName Name RegionalDisplayName + ------------------------ ------------------- ------------------------------------- + East US eastus (US) East US + East US 2 eastus2 (US) East US 2 + South Central US southcentralus (US) South Central US + ... + ``` + + Anota el valor de la columna `Name` de la región más cercana a ti. Puedes encontrar las regiones en un mapa en la [página de geografías de Azure](https://azure.microsoft.com/global-infrastructure/geographies/?WT.mc_id=academic-17441-jabenn). + +1. Ejecuta el siguiente comando para crear un grupo de recursos llamado `soil-moisture-sensor`. Los nombres de los grupos de recursos deben ser únicos en tu suscripción. + + ```sh + az group create --name soil-moisture-sensor \ + --location + ``` + + Sustituye `` por la ubicación que seleccionaste en el paso anterior. + +### Tarea - crear un IoT Hub + +Ahora puedes crear un recurso IoT Hub en tu grupo de recursos. + +1. Usa el siguiente comando para crear tu recurso IoT Hub: + + ```sh + az iot hub create --resource-group soil-moisture-sensor \ + --sku F1 \ + --partition-count 2 \ + --name + ``` + + Sustituye `` por un nombre para tu hub. Este nombre debe ser único a nivel global, es decir, ningún otro IoT Hub creado por alguien más puede tener el mismo nombre. Este nombre se utiliza en una URL que apunta al hub, por lo que debe ser único. Usa algo como `soil-moisture-sensor-` y añade un identificador único al final, como algunas palabras aleatorias o tu nombre. + + La opción `--sku F1` indica que se usará un nivel gratuito. El nivel gratuito admite 8,000 mensajes al día junto con la mayoría de las características de los niveles de precio completo. + + > 🎓 Los diferentes niveles de precios de los servicios de Azure se denominan niveles. Cada nivel tiene un costo diferente y proporciona diferentes características o volúmenes de datos. + + > 💁 Si deseas aprender más sobre los precios, puedes consultar la [guía de precios de Azure IoT Hub](https://azure.microsoft.com/pricing/details/iot-hub/?WT.mc_id=academic-17441-jabenn). + + La opción `--partition-count 2` define cuántos flujos de datos admite el IoT Hub. Más particiones reducen el bloqueo de datos cuando múltiples dispositivos leen y escriben desde el IoT Hub. Las particiones están fuera del alcance de estas lecciones, pero este valor debe configurarse para crear un IoT Hub de nivel gratuito. + + > 💁 Solo puedes tener un IoT Hub de nivel gratuito por suscripción. + +El IoT Hub se creará. Esto puede tardar un minuto o más en completarse. + +## Comunicarte con IoT Hub + +En la lección anterior, usaste MQTT y enviaste mensajes de ida y vuelta en diferentes temas, con diferentes propósitos. En lugar de enviar mensajes en diferentes temas, IoT Hub tiene varias formas definidas para que el dispositivo se comunique con el Hub, o para que el Hub se comunique con el dispositivo. + +> 💁 En el fondo, esta comunicación entre IoT Hub y tu dispositivo puede usar MQTT, HTTPS o AMQP. + +* Mensajes de dispositivo a nube (D2C) - estos son mensajes enviados desde un dispositivo a IoT Hub, como telemetría. Luego pueden ser leídos desde IoT Hub por tu código de aplicación. + + > 🎓 En el fondo, IoT Hub utiliza un servicio de Azure llamado [Event Hubs](https://docs.microsoft.com/azure/event-hubs/?WT.mc_id=academic-17441-jabenn). Cuando escribes código para leer mensajes enviados al hub, a menudo se les llama eventos. + +* Mensajes de nube a dispositivo (C2D) - estos son mensajes enviados desde el código de la aplicación, a través de un IoT Hub, a un dispositivo IoT. + +* Solicitudes de métodos directos - estos son mensajes enviados desde el código de la aplicación a través de un IoT Hub a un dispositivo IoT para solicitar que el dispositivo haga algo, como controlar un actuador. Estos mensajes requieren una respuesta para que tu código de aplicación pueda saber si se procesaron correctamente. + +* Gemelos de dispositivos - estos son documentos JSON sincronizados entre el dispositivo y IoT Hub, y se utilizan para almacenar configuraciones u otras propiedades informadas por el dispositivo, o que deben configurarse en el dispositivo (conocidas como deseadas) por IoT Hub. + +IoT Hub puede almacenar mensajes y solicitudes de métodos directos durante un período de tiempo configurable (por defecto un día), por lo que si un dispositivo o el código de la aplicación pierde conexión, aún puede recuperar los mensajes enviados mientras estaba desconectado una vez que se reconecta. Los gemelos de dispositivos se mantienen permanentemente en IoT Hub, por lo que en cualquier momento un dispositivo puede reconectarse y obtener el gemelo de dispositivo más reciente. + +✅ Investiga: Lee más sobre estos tipos de mensajes en la [guía de comunicaciones de dispositivo a nube](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-d2c-guidance?WT.mc_id=academic-17441-jabenn) y la [guía de comunicaciones de nube a dispositivo](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-c2d-guidance?WT.mc_id=academic-17441-jabenn) en la documentación de IoT Hub. + +## Conecta tu dispositivo al servicio IoT + +Una vez que el hub esté creado, tu dispositivo IoT puede conectarse a él. Solo los dispositivos registrados pueden conectarse a un servicio, por lo que primero deberás registrar tu dispositivo. Cuando lo registres, obtendrás una cadena de conexión que el dispositivo puede usar para conectarse. Esta cadena de conexión es específica del dispositivo e incluye información sobre el IoT Hub, el dispositivo y una clave secreta que permitirá que este dispositivo se conecte. + +> 🎓 Una cadena de conexión es un término genérico para un texto que contiene detalles de conexión. Estas se usan al conectarse a IoT Hubs, bases de datos y muchos otros servicios. Generalmente consisten en un identificador para el servicio, como una URL, y datos de seguridad como una clave secreta. Estas se pasan a los SDKs para conectarse al servicio. + +> ⚠️ ¡Las cadenas de conexión deben mantenerse seguras! La seguridad se cubrirá con más detalle en una lección futura. + +### Tarea - registrar tu dispositivo IoT + +El dispositivo IoT puede registrarse en tu IoT Hub usando Azure CLI. + +1. Ejecuta el siguiente comando para registrar un dispositivo: + + ```sh + az iot hub device-identity create --device-id soil-moisture-sensor \ + --hub-name + ``` + + Sustituye `` por el nombre que usaste para tu IoT Hub. + + Esto creará un dispositivo con un ID de `soil-moisture-sensor`. + +1. Cuando tu dispositivo IoT se conecte a tu IoT Hub usando el SDK, necesitará usar una cadena de conexión que proporcione la URL del hub, junto con una clave secreta. Ejecuta el siguiente comando para obtener la cadena de conexión: + + ```sh + az iot hub device-identity connection-string show --device-id soil-moisture-sensor \ + --output table \ + --hub-name + ``` + + Sustituye `` por el nombre que usaste para tu IoT Hub. + +1. Guarda la cadena de conexión que aparece en la salida, ya que la necesitarás más adelante. + +### Tarea - conectar tu dispositivo IoT a la nube + +Sigue la guía correspondiente para conectar tu dispositivo IoT a la nube: + +* [Arduino - Wio Terminal](wio-terminal-connect-hub.md) +* [Computadora de placa única - Raspberry Pi/Dispositivo IoT virtual](single-board-computer-connect-hub.md) + +### Tarea - monitorear eventos + +Por ahora, no actualizarás tu código de servidor. En su lugar, puedes usar Azure CLI para monitorear eventos desde tu dispositivo IoT. + +1. Asegúrate de que tu dispositivo IoT esté funcionando y enviando valores de telemetría de humedad del suelo. + +1. Ejecuta el siguiente comando en tu terminal para monitorear los mensajes enviados a tu IoT Hub: + + ```sh + az iot hub monitor-events --hub-name + ``` + + Sustituye `` por el nombre que usaste para tu IoT Hub. + + Verás mensajes aparecer en la salida de la consola a medida que son enviados por tu dispositivo IoT. + + ```output + Starting event monitor, use ctrl-c to stop... + { + "event": { + "origin": "soil-moisture-sensor", + "module": "", + "interface": "", + "component": "", + "payload": "{\"soil_moisture\": 376}" + } + }, + { + "event": { + "origin": "soil-moisture-sensor", + "module": "", + "interface": "", + "component": "", + "payload": "{\"soil_moisture\": 381}" + } + } + ``` + + El contenido del `payload` coincidirá con el mensaje enviado por tu dispositivo IoT. + + > En el momento de escribir esto, la extensión `az iot` no funciona completamente en dispositivos Apple Silicon. Si estás usando un dispositivo Apple Silicon, necesitarás monitorear los mensajes de otra manera, como usando las [herramientas de Azure IoT para Visual Studio Code](https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-vscode-iot-toolkit-cloud-device-messaging). + +1. Estos mensajes tienen una serie de propiedades adjuntas automáticamente, como la marca de tiempo en que fueron enviados. Estas se conocen como *anotaciones*. Para ver todas las anotaciones de los mensajes, usa el siguiente comando: + + ```sh + az iot hub monitor-events --properties anno --hub-name + ``` + + Sustituye `` por el nombre que usaste para tu IoT Hub. + + Verás mensajes aparecer en la salida de la consola a medida que son enviados por tu dispositivo IoT. + + ```output + Starting event monitor, use ctrl-c to stop... + { + "event": { + "origin": "soil-moisture-sensor", + "module": "", + "interface": "", + "component": "", + "properties": {}, + "annotations": { + "iothub-connection-device-id": "soil-moisture-sensor", + "iothub-connection-auth-method": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}", + "iothub-connection-auth-generation-id": "637553997165220462", + "iothub-enqueuedtime": 1619976150288, + "iothub-message-source": "Telemetry", + "x-opt-sequence-number": 1379, + "x-opt-offset": "550576", + "x-opt-enqueued-time": 1619976150277 + }, + "payload": "{\"soil_moisture\": 381}" + } + } + ``` + + Los valores de tiempo en las anotaciones están en [tiempo UNIX](https://wikipedia.org/wiki/Unix_time), que representa el número de segundos desde la medianoche del 1er de enero de 1970. + + Sal del monitor de eventos cuando hayas terminado. + +### Tarea - controlar tu dispositivo IoT + +También puedes usar Azure CLI para llamar métodos directos en tu dispositivo IoT. + +1. Ejecuta el siguiente comando en tu terminal para invocar el método `relay_on` en el dispositivo IoT: + + ```sh + az iot hub invoke-device-method --device-id soil-moisture-sensor \ + --method-name relay_on \ + --method-payload '{}' \ + --hub-name + ``` + + Sustituye ` + +` con el nombre que usaste para tu IoT Hub. + + Esto envía una solicitud de método directo para el método especificado por `method-name`. Los métodos directos pueden incluir un payload que contenga datos para el método, y esto se puede especificar en el parámetro `method-payload` como JSON. + + Verás que el relé se enciende y el correspondiente resultado de tu dispositivo IoT: + + ```output + Direct method received - relay_on + ``` + +1. Repite el paso anterior, pero establece el `--method-name` en `relay_off`. Verás que el relé se apaga y el correspondiente resultado del dispositivo IoT. + +--- + +## 🚀 Desafío + +El nivel gratuito de IoT Hub permite 8,000 mensajes al día. El código que escribiste envía mensajes de telemetría cada 10 segundos. ¿Cuántos mensajes al día se generan si se envía un mensaje cada 10 segundos? + +Piensa en la frecuencia con la que deberían enviarse las mediciones de humedad del suelo. ¿Cómo puedes cambiar tu código para permanecer dentro del nivel gratuito y verificar tan frecuentemente como sea necesario pero no demasiado? ¿Qué pasaría si quisieras agregar un segundo dispositivo? + +## Cuestionario posterior a la clase + +[Cuestionario posterior a la clase](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/16) + +## Revisión y autoestudio + +El SDK de IoT Hub es de código abierto tanto para Arduino como para Python. En los repositorios de código en GitHub hay varios ejemplos que muestran cómo trabajar con diferentes características de IoT Hub. + +* Si estás usando un Wio Terminal, revisa los [ejemplos de Arduino en GitHub](https://github.com/Azure/azure-iot-pal-arduino/tree/master/pal/samples) +* Si estás usando un Raspberry Pi o un dispositivo virtual, revisa los [ejemplos de Python en GitHub](https://github.com/Azure/azure-iot-sdk-python/tree/master/azure-iot-hub/samples) + +## Tarea + +[Aprende sobre servicios en la nube](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/assignment.md b/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/assignment.md new file mode 100644 index 00000000..c67145a6 --- /dev/null +++ b/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/assignment.md @@ -0,0 +1,33 @@ + +# Aprende sobre servicios en la nube + +## Instrucciones + +Las nubes, como Azure de Microsoft, ofrecen más que solo computación para alquilar. Los principales tipos de servicios en la nube incluyen: + +* Infraestructura como servicio (IaaS) +* Plataforma como servicio (PaaS) +* Serverless +* Software como servicio (SaaS) + +Aprende sobre estos diferentes tipos de servicios y explica qué son y en qué se diferencian. Explica cuáles de estos servicios son relevantes para los desarrolladores de IoT. + +## Rúbrica + +| Criterios | Ejemplar | Adecuado | Necesita Mejorar | +| --------- | -------- | -------- | ---------------- | +| Explica los diferentes servicios en la nube | Dio explicaciones claras de los 4 tipos de servicios | Fue capaz de explicar 3 tipos de servicios | Solo pudo explicar 1 o 2 de los servicios | +| Explica qué servicio es relevante para IoT | Describió una explicación de cuáles servicios son relevantes para los desarrolladores de IoT y por qué | Describió una explicación de cuáles servicios son relevantes para los desarrolladores de IoT pero no por qué | No pudo describir cuáles servicios son relevantes para los desarrolladores de IoT | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/single-board-computer-connect-hub.md b/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/single-board-computer-connect-hub.md new file mode 100644 index 00000000..a2acfe0b --- /dev/null +++ b/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/single-board-computer-connect-hub.md @@ -0,0 +1,130 @@ + +# Conecta tu dispositivo IoT a la nube - Hardware IoT virtual y Raspberry Pi + +En esta parte de la lección, conectarás tu dispositivo IoT virtual o Raspberry Pi a tu IoT Hub para enviar telemetría y recibir comandos. + +## Conecta tu dispositivo al IoT Hub + +El siguiente paso es conectar tu dispositivo al IoT Hub. + +### Tarea - conectar al IoT Hub + +1. Abre la carpeta `soil-moisture-sensor` en VS Code. Asegúrate de que el entorno virtual esté ejecutándose en la terminal si estás utilizando un dispositivo IoT virtual. + +1. Instala algunos paquetes adicionales de Pip: + + ```sh + pip3 install azure-iot-device + ``` + + `azure-iot-device` es una biblioteca para comunicarse con tu IoT Hub. + +1. Agrega las siguientes importaciones en la parte superior del archivo `app.py`, debajo de las importaciones existentes: + + ```python + from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse + ``` + + Este código importa el SDK para comunicarse con tu IoT Hub. + +1. Elimina la línea `import paho.mqtt.client as mqtt`, ya que esta biblioteca ya no es necesaria. Elimina todo el código relacionado con MQTT, incluidos los nombres de los temas, todo el código que utiliza `mqtt_client` y la función `handle_command`. Conserva el bucle `while True:`, pero elimina la línea `mqtt_client.publish` de este bucle. + +1. Agrega el siguiente código debajo de las declaraciones de importación: + + ```python + connection_string = "" + ``` + + Sustituye `` por la cadena de conexión que recuperaste para el dispositivo anteriormente en esta lección. + + > 💁 Esto no es una buena práctica. Las cadenas de conexión nunca deben almacenarse en el código fuente, ya que pueden ser registradas en el control de código fuente y encontradas por cualquiera. Estamos haciendo esto aquí por simplicidad. Idealmente, deberías usar algo como una variable de entorno y una herramienta como [`python-dotenv`](https://pypi.org/project/python-dotenv/). Aprenderás más sobre esto en una lección futura. + +1. Debajo de este código, agrega lo siguiente para crear un objeto cliente del dispositivo que pueda comunicarse con el IoT Hub y conectarlo: + + ```python + device_client = IoTHubDeviceClient.create_from_connection_string(connection_string) + + print('Connecting') + device_client.connect() + print('Connected') + ``` + +1. Ejecuta este código. Verás que tu dispositivo se conecta. + + ```output + pi@raspberrypi:~/soil-moisture-sensor $ python3 app.py + Connecting + Connected + Soil moisture: 379 + ``` + +## Enviar telemetría + +Ahora que tu dispositivo está conectado, puedes enviar telemetría al IoT Hub en lugar del broker MQTT. + +### Tarea - enviar telemetría + +1. Agrega el siguiente código dentro del bucle `while True`, justo antes de la pausa: + + ```python + message = Message(json.dumps({ 'soil_moisture': soil_moisture })) + device_client.send_message(message) + ``` + + Este código crea un `Message` de IoT Hub que contiene la lectura de humedad del suelo como una cadena JSON, y luego lo envía al IoT Hub como un mensaje de dispositivo a nube. + +## Manejar comandos + +Tu dispositivo necesita manejar un comando del código del servidor para controlar el relé. Esto se envía como una solicitud de método directo. + +## Tarea - manejar una solicitud de método directo + +1. Agrega el siguiente código antes del bucle `while True`: + + ```python + def handle_method_request(request): + print("Direct method received - ", request.name) + + if request.name == "relay_on": + relay.on() + elif request.name == "relay_off": + relay.off() + ``` + + Esto define un método, `handle_method_request`, que será llamado cuando el IoT Hub invoque un método directo. Cada método directo tiene un nombre, y este código espera un método llamado `relay_on` para encender el relé, y `relay_off` para apagarlo. + + > 💁 Esto también podría implementarse en una única solicitud de método directo, pasando el estado deseado del relé en un payload que puede ser enviado con la solicitud del método y estar disponible desde el objeto `request`. + +1. Los métodos directos requieren una respuesta para informar al código que los invocó que han sido manejados. Agrega el siguiente código al final de la función `handle_method_request` para crear una respuesta a la solicitud: + + ```python + method_response = MethodResponse.create_from_method_request(request, 200) + device_client.send_method_response(method_response) + ``` + + Este código envía una respuesta a la solicitud de método directo con un código de estado HTTP 200, y la envía de vuelta al IoT Hub. + +1. Agrega el siguiente código debajo de esta definición de función: + + ```python + device_client.on_method_request_received = handle_method_request + ``` + + Este código indica al cliente del IoT Hub que llame a la función `handle_method_request` cuando se invoque un método directo. + +> 💁 Puedes encontrar este código en la carpeta [code/pi](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud/code/pi) o [code/virtual-device](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud/code/virtual-device). + +😀 ¡Tu programa del sensor de humedad del suelo está conectado a tu IoT Hub! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/wio-terminal-connect-hub.md b/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/wio-terminal-connect-hub.md new file mode 100644 index 00000000..41a043cf --- /dev/null +++ b/translations/es/2-farm/lessons/4-migrate-your-plant-to-the-cloud/wio-terminal-connect-hub.md @@ -0,0 +1,306 @@ + +# Conecta tu dispositivo IoT a la nube - Wio Terminal + +En esta parte de la lección, conectarás tu Wio Terminal a tu IoT Hub para enviar telemetría y recibir comandos. + +## Conecta tu dispositivo a IoT Hub + +El siguiente paso es conectar tu dispositivo a IoT Hub. + +### Tarea - conectar a IoT Hub + +1. Abre el proyecto `soil-moisture-sensor` en VS Code. + +1. Abre el archivo `platformio.ini`. Elimina la dependencia de la biblioteca `knolleary/PubSubClient`. Esta se utilizaba para conectarse al broker MQTT público y no es necesaria para conectarse a IoT Hub. + +1. Agrega las siguientes dependencias de biblioteca: + + ```ini + seeed-studio/Seeed Arduino RTC @ 2.0.0 + arduino-libraries/AzureIoTHub @ 1.6.0 + azure/AzureIoTUtility @ 1.6.1 + azure/AzureIoTProtocol_MQTT @ 1.6.0 + azure/AzureIoTProtocol_HTTP @ 1.6.0 + azure/AzureIoTSocket_WiFi @ 1.0.2 + ``` + + La biblioteca `Seeed Arduino RTC` proporciona código para interactuar con un reloj en tiempo real en el Wio Terminal, utilizado para rastrear el tiempo. Las bibliotecas restantes permiten que tu dispositivo IoT se conecte a IoT Hub. + +1. Agrega lo siguiente al final del archivo `platformio.ini`: + + ```ini + build_flags = + -DDONT_USE_UPLOADTOBLOB + ``` + + Esto establece una bandera del compilador que es necesaria al compilar el código de Arduino IoT Hub. + +1. Abre el archivo de encabezado `config.h`. Elimina todas las configuraciones de MQTT y agrega la siguiente constante para la cadena de conexión del dispositivo: + + ```cpp + // IoT Hub settings + const char *CONNECTION_STRING = ""; + ``` + + Reemplaza `` con la cadena de conexión de tu dispositivo que copiaste anteriormente. + +1. La conexión a IoT Hub utiliza un token basado en tiempo. Esto significa que el dispositivo IoT necesita conocer la hora actual. A diferencia de sistemas operativos como Windows, macOS o Linux, los microcontroladores no sincronizan automáticamente la hora actual a través de Internet. Esto significa que deberás agregar código para obtener la hora actual de un servidor [NTP](https://wikipedia.org/wiki/Network_Time_Protocol). Una vez que se haya obtenido la hora, se puede almacenar en un reloj en tiempo real en el Wio Terminal, permitiendo solicitar la hora correcta en una fecha posterior, suponiendo que el dispositivo no pierda energía. Agrega un nuevo archivo llamado `ntp.h` con el siguiente código: + + ```cpp + #pragma once + + #include "DateTime.h" + #include + #include "samd/NTPClientAz.h" + #include + + static void initTime() + { + WiFiUDP _udp; + time_t epochTime = (time_t)-1; + NTPClientAz ntpClient; + + ntpClient.begin(); + + while (true) + { + epochTime = ntpClient.getEpochTime("0.pool.ntp.org"); + + if (epochTime == (time_t)-1) + { + Serial.println("Fetching NTP epoch time failed! Waiting 2 seconds to retry."); + delay(2000); + } + else + { + Serial.print("Fetched NTP epoch time is: "); + + char buff[32]; + sprintf(buff, "%.f", difftime(epochTime, (time_t)0)); + Serial.println(buff); + break; + } + } + + ntpClient.end(); + + struct timeval tv; + tv.tv_sec = epochTime; + tv.tv_usec = 0; + + settimeofday(&tv, NULL); + } + ``` + + Los detalles de este código están fuera del alcance de esta lección. Define una función llamada `initTime` que obtiene la hora actual de un servidor NTP y la utiliza para configurar el reloj en el Wio Terminal. + +1. Abre el archivo `main.cpp` y elimina todo el código de MQTT, incluyendo el archivo de encabezado `PubSubClient.h`, la declaración de la variable `PubSubClient`, los métodos `reconnectMQTTClient` y `createMQTTClient`, y cualquier llamada a estas variables y métodos. Este archivo solo debe contener código para conectarse a WiFi, obtener la humedad del suelo y crear un documento JSON con esta información. + +1. Agrega las siguientes directivas `#include` al inicio del archivo `main.cpp` para incluir archivos de encabezado de las bibliotecas de IoT Hub y para configurar la hora: + + ```cpp + #include + #include + #include + #include "ntp.h" + ``` + +1. Agrega la siguiente llamada al final de la función `setup` para configurar la hora actual: + + ```cpp + initTime(); + ``` + +1. Agrega la siguiente declaración de variable al inicio del archivo, justo debajo de las directivas de inclusión: + + ```cpp + IOTHUB_DEVICE_CLIENT_LL_HANDLE _device_ll_handle; + ``` + + Esto declara un `IOTHUB_DEVICE_CLIENT_LL_HANDLE`, un identificador para una conexión a IoT Hub. + +1. Debajo de esto, agrega el siguiente código: + + ```cpp + static void connectionStatusCallback(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void *user_context) + { + if (result == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED) + { + Serial.println("The device client is connected to iothub"); + } + else + { + Serial.println("The device client has been disconnected"); + } + } + ``` + + Esto declara una función de callback que será llamada cuando la conexión a IoT Hub cambie de estado, como conectarse o desconectarse. El estado se envía al puerto serial. + +1. Debajo de esto, agrega una función para conectarse a IoT Hub: + + ```cpp + void connectIoTHub() + { + IoTHub_Init(); + + _device_ll_handle = IoTHubDeviceClient_LL_CreateFromConnectionString(CONNECTION_STRING, MQTT_Protocol); + + if (_device_ll_handle == NULL) + { + Serial.println("Failure creating Iothub device. Hint: Check your connection string."); + return; + } + + IoTHubDeviceClient_LL_SetConnectionStatusCallback(_device_ll_handle, connectionStatusCallback, NULL); + } + ``` + + Este código inicializa el código de la biblioteca de IoT Hub y luego crea una conexión utilizando la cadena de conexión en el archivo de encabezado `config.h`. Esta conexión se basa en MQTT. Si la conexión falla, esto se envía al puerto serial; si ves esto en la salida, verifica la cadena de conexión. Finalmente, se configura el callback de estado de conexión. + +1. Llama a esta función en la función `setup` debajo de la llamada a `initTime`: + + ```cpp + connectIoTHub(); + ``` + +1. Al igual que con el cliente MQTT, este código se ejecuta en un solo hilo, por lo que necesita tiempo para procesar los mensajes enviados por el hub y enviados al hub. Agrega lo siguiente al inicio de la función `loop` para hacer esto: + + ```cpp + IoTHubDeviceClient_LL_DoWork(_device_ll_handle); + ``` + +1. Compila y sube este código. Verás la conexión en el monitor serial: + + ```output + Connecting to WiFi.. + Connected! + Fetched NTP epoch time is: 1619983687 + Sending telemetry {"soil_moisture":391} + The device client is connected to iothub + ``` + + En la salida puedes ver que se obtiene la hora NTP, seguido de la conexión del cliente del dispositivo. Puede tardar unos segundos en conectarse, por lo que puedes ver la humedad del suelo en la salida mientras el dispositivo se conecta. + + > 💁 Puedes convertir el tiempo UNIX del NTP a una versión más legible utilizando un sitio web como [unixtimestamp.com](https://www.unixtimestamp.com) + +## Enviar telemetría + +Ahora que tu dispositivo está conectado, puedes enviar telemetría a IoT Hub en lugar del broker MQTT. + +### Tarea - enviar telemetría + +1. Agrega la siguiente función encima de la función `setup`: + + ```cpp + void sendTelemetry(const char *telemetry) + { + IOTHUB_MESSAGE_HANDLE message_handle = IoTHubMessage_CreateFromString(telemetry); + IoTHubDeviceClient_LL_SendEventAsync(_device_ll_handle, message_handle, NULL, NULL); + IoTHubMessage_Destroy(message_handle); + } + ``` + + Este código crea un mensaje de IoT Hub a partir de una cadena pasada como parámetro, lo envía al hub y luego limpia el objeto del mensaje. + +1. Llama a este código en la función `loop`, justo después de la línea donde la telemetría se envía al puerto serial: + + ```cpp + sendTelemetry(telemetry.c_str()); + ``` + +## Manejar comandos + +Tu dispositivo necesita manejar un comando del código del servidor para controlar el relé. Esto se envía como una solicitud de método directo. + +## Tarea - manejar una solicitud de método directo + +1. Agrega el siguiente código antes de la función `connectIoTHub`: + + ```cpp + int directMethodCallback(const char *method_name, const unsigned char *payload, size_t size, unsigned char **response, size_t *response_size, void *userContextCallback) + { + Serial.printf("Direct method received %s\r\n", method_name); + + if (strcmp(method_name, "relay_on") == 0) + { + digitalWrite(PIN_WIRE_SCL, HIGH); + } + else if (strcmp(method_name, "relay_off") == 0) + { + digitalWrite(PIN_WIRE_SCL, LOW); + } + } + ``` + + Este código define un método de callback que la biblioteca de IoT Hub puede llamar cuando recibe una solicitud de método directo. El método solicitado se envía en el parámetro `method_name`. Esta función imprime el método llamado en el puerto serial y luego enciende o apaga el relé dependiendo del nombre del método. + + > 💁 Esto también podría implementarse en un único método directo, pasando el estado deseado del relé en un payload que puede ser pasado con la solicitud de método y disponible desde el parámetro `payload`. + +1. Agrega el siguiente código al final de la función `directMethodCallback`: + + ```cpp + char resultBuff[16]; + sprintf(resultBuff, "{\"Result\":\"\"}"); + *response_size = strlen(resultBuff); + *response = (unsigned char *)malloc(*response_size); + memcpy(*response, resultBuff, *response_size); + + return IOTHUB_CLIENT_OK; + ``` + + Las solicitudes de método directo necesitan una respuesta, y la respuesta tiene dos partes: una respuesta como texto y un código de retorno. Este código creará un resultado como el siguiente documento JSON: + + ```JSON + { + "Result": "" + } + ``` + + Esto luego se copia en el parámetro `response`, y el tamaño de esta respuesta se establece en el parámetro `response_size`. Este código luego devuelve `IOTHUB_CLIENT_OK` para mostrar que el método fue manejado correctamente. + +1. Conecta el callback agregando lo siguiente al final de la función `connectIoTHub`: + + ```cpp + IoTHubClient_LL_SetDeviceMethodCallback(_device_ll_handle, directMethodCallback, NULL); + ``` + +1. La función `loop` llamará a la función `IoTHubDeviceClient_LL_DoWork` para procesar eventos enviados por IoT Hub. Esto solo se llama cada 10 segundos debido al `delay`, lo que significa que los métodos directos solo se procesan cada 10 segundos. Para hacerlo más eficiente, el retraso de 10 segundos puede implementarse como muchos retrasos más cortos, llamando a `IoTHubDeviceClient_LL_DoWork` cada vez. Para hacer esto, agrega el siguiente código encima de la función `loop`: + + ```cpp + void work_delay(int delay_time) + { + int current = 0; + do + { + IoTHubDeviceClient_LL_DoWork(_device_ll_handle); + delay(100); + current += 100; + } while (current < delay_time); + } + ``` + + Este código repetirá el bucle, llamando a `IoTHubDeviceClient_LL_DoWork` y retrasando 100ms cada vez. Hará esto tantas veces como sea necesario para retrasar la cantidad de tiempo dada en el parámetro `delay_time`. Esto significa que el dispositivo está esperando como máximo 100ms para procesar solicitudes de método directo. + +1. En la función `loop`, elimina la llamada a `IoTHubDeviceClient_LL_DoWork` y reemplaza la llamada `delay(10000)` con lo siguiente para llamar a esta nueva función: + + ```cpp + work_delay(10000); + ``` + +> 💁 Puedes encontrar este código en la carpeta [code/wio-terminal](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud/code/wio-terminal). + +😀 ¡Tu programa de sensor de humedad del suelo está conectado a tu IoT Hub! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/5-migrate-application-to-the-cloud/README.md b/translations/es/2-farm/lessons/5-migrate-application-to-the-cloud/README.md new file mode 100644 index 00000000..8212a2ea --- /dev/null +++ b/translations/es/2-farm/lessons/5-migrate-application-to-the-cloud/README.md @@ -0,0 +1,656 @@ + +# Migra la lógica de tu aplicación a la nube + +![Una ilustración resumen de esta lección](../../../../../translated_images/lesson-9.dfe99c8e891f48e179724520da9f5794392cf9a625079281ccdcbf09bd85e1b6.es.jpg) + +> Ilustración por [Nitya Narasimhan](https://github.com/nitya). Haz clic en la imagen para una versión más grande. + +Esta lección fue impartida como parte de la serie [IoT para principiantes Proyecto 2 - Agricultura Digital](https://youtube.com/playlist?list=PLmsFUfdnGr3yCutmcVg6eAUEfsGiFXgcx) del [Microsoft Reactor](https://developer.microsoft.com/reactor/?WT.mc_id=academic-17441-jabenn). + +[![Controla tu dispositivo IoT con código sin servidor](https://img.youtube.com/vi/VVZDcs5u1_I/0.jpg)](https://youtu.be/VVZDcs5u1_I) + +## Cuestionario previo a la lección + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/17) + +## Introducción + +En la última lección, aprendiste cómo conectar el monitoreo de humedad del suelo de tus plantas y el control del relé a un servicio IoT basado en la nube. El siguiente paso es mover el código del servidor que controla el tiempo del relé a la nube. En esta lección, aprenderás cómo hacerlo utilizando funciones sin servidor. + +En esta lección cubriremos: + +* [¿Qué es sin servidor?](../../../../../2-farm/lessons/5-migrate-application-to-the-cloud) +* [Crear una aplicación sin servidor](../../../../../2-farm/lessons/5-migrate-application-to-the-cloud) +* [Crear un disparador de eventos para IoT Hub](../../../../../2-farm/lessons/5-migrate-application-to-the-cloud) +* [Enviar solicitudes de método directo desde código sin servidor](../../../../../2-farm/lessons/5-migrate-application-to-the-cloud) +* [Desplegar tu código sin servidor en la nube](../../../../../2-farm/lessons/5-migrate-application-to-the-cloud) + +## ¿Qué es sin servidor? + +Sin servidor, o computación sin servidor, implica crear pequeños bloques de código que se ejecutan en la nube en respuesta a diferentes tipos de eventos. Cuando ocurre el evento, tu código se ejecuta y recibe datos sobre el evento. Estos eventos pueden provenir de muchas fuentes, como solicitudes web, mensajes en una cola, cambios en datos de una base de datos o mensajes enviados a un servicio IoT por dispositivos IoT. + +![Eventos enviados desde un servicio IoT a un servicio sin servidor, todos procesados al mismo tiempo por múltiples funciones en ejecución](../../../../../translated_images/iot-messages-to-serverless.0194da1cc0732bb7d0f823aed3fce54735c6b1ad3bf36089804d8aaefc0a774f.es.png) + +> 💁 Si has usado disparadores de bases de datos antes, puedes pensar en esto como algo similar: código que se activa por un evento como insertar una fila. + +![Cuando se envían muchos eventos al mismo tiempo, el servicio sin servidor escala para ejecutarlos todos simultáneamente](../../../../../translated_images/serverless-scaling.f8c769adf0413fd17be1af4f07ff63016b347e2ff869be6c4abb211f9e93909d.es.png) + +Tu código solo se ejecuta cuando ocurre el evento; no hay nada manteniendo tu código activo en otros momentos. El evento ocurre, tu código se carga y se ejecuta. Esto hace que el modelo sin servidor sea muy escalable: si muchos eventos ocurren al mismo tiempo, el proveedor de la nube puede ejecutar tu función tantas veces como sea necesario simultáneamente en los servidores disponibles. La desventaja de esto es que si necesitas compartir información entre eventos, debes guardarla en algún lugar como una base de datos en lugar de almacenarla en memoria. + +Tu código se escribe como una función que toma detalles sobre el evento como parámetro. Puedes usar una amplia gama de lenguajes de programación para escribir estas funciones sin servidor. + +> 🎓 Sin servidor también se conoce como Funciones como servicio (FaaS) ya que cada disparador de evento se implementa como una función en el código. + +A pesar del nombre, sin servidor sí utiliza servidores. El nombre se debe a que, como desarrollador, no te preocupas por los servidores necesarios para ejecutar tu código; solo te importa que tu código se ejecute en respuesta a un evento. El proveedor de la nube tiene un *runtime* sin servidor que gestiona la asignación de servidores, redes, almacenamiento, CPU, memoria y todo lo necesario para ejecutar tu código. Este modelo significa que no pagas por servidor, ya que no hay un servidor específico. En cambio, pagas por el tiempo que tu código está en ejecución y la cantidad de memoria utilizada. + +> 💰 Sin servidor es una de las formas más económicas de ejecutar código en la nube. Por ejemplo, al momento de escribir esto, un proveedor de nube permite que todas tus funciones sin servidor se ejecuten un total combinado de 1,000,000 veces al mes antes de comenzar a cobrarte, y después de eso cobran US$0.20 por cada 1,000,000 ejecuciones. Cuando tu código no está en ejecución, no pagas. + +Como desarrollador de IoT, el modelo sin servidor es ideal. Puedes escribir una función que se llame en respuesta a mensajes enviados desde cualquier dispositivo IoT conectado a tu servicio IoT alojado en la nube. Tu código manejará todos los mensajes enviados, pero solo estará en ejecución cuando sea necesario. + +✅ Revisa el código que escribiste como servidor escuchando mensajes a través de MQTT. ¿Cómo podría ejecutarse esto en la nube utilizando sin servidor? ¿Cómo crees que el código podría cambiar para admitir computación sin servidor? + +> 💁 El modelo sin servidor se está expandiendo a otros servicios en la nube además de ejecutar código. Por ejemplo, las bases de datos sin servidor están disponibles en la nube utilizando un modelo de precios sin servidor donde pagas por cada solicitud realizada contra la base de datos, como una consulta o inserción, generalmente con precios basados en la cantidad de trabajo necesario para atender la solicitud. Por ejemplo, una sola selección de una fila contra una clave primaria costará menos que una operación complicada que une muchas tablas y devuelve miles de filas. + +## Crear una aplicación sin servidor + +El servicio de computación sin servidor de Microsoft se llama Azure Functions. + +![El logo de Azure Functions](../../../../../translated_images/azure-functions-logo.1cfc8e3204c9c44aaf80fcf406fc8544d80d7f00f8d3e8ed6fed764563e17564.es.png) + +El siguiente video corto ofrece una visión general de Azure Functions. + +[![Video de introducción a Azure Functions](https://img.youtube.com/vi/8-jz5f_JyEQ/0.jpg)](https://www.youtube.com/watch?v=8-jz5f_JyEQ) + +> 🎥 Haz clic en la imagen de arriba para ver el video. + +✅ Tómate un momento para investigar y leer la visión general de Azure Functions en la [documentación de Microsoft Azure Functions](https://docs.microsoft.com/azure/azure-functions/functions-overview?WT.mc_id=academic-17441-jabenn). + +Para escribir Azure Functions, comienzas con una aplicación de Azure Functions en el lenguaje de tu elección. Azure Functions admite de forma nativa Python, JavaScript, TypeScript, C#, F#, Java y Powershell. En esta lección aprenderás cómo escribir una aplicación de Azure Functions en Python. + +> 💁 Azure Functions también admite controladores personalizados, por lo que puedes escribir tus funciones en cualquier lenguaje que soporte solicitudes HTTP, incluidos lenguajes más antiguos como COBOL. + +Las aplicaciones de funciones consisten en uno o más *disparadores* - funciones que responden a eventos. Puedes tener múltiples disparadores dentro de una aplicación de funciones, todos compartiendo una configuración común. Por ejemplo, en el archivo de configuración de tu aplicación de funciones puedes tener los detalles de conexión de tu IoT Hub, y todas las funciones en la aplicación pueden usar esto para conectarse y escuchar eventos. + +### Tarea - instalar las herramientas de Azure Functions + +> Al momento de escribir esto, las herramientas de código de Azure Functions no funcionan completamente en Apple Silicon con proyectos de Python. Necesitarás usar una Mac basada en Intel, una PC con Windows o una PC con Linux. + +Una gran característica de Azure Functions es que puedes ejecutarlas localmente. El mismo runtime que se utiliza en la nube puede ejecutarse en tu computadora, permitiéndote escribir código que responde a mensajes IoT y ejecutarlo localmente. Incluso puedes depurar tu código mientras se manejan eventos. Una vez que estés satisfecho con tu código, puedes desplegarlo en la nube. + +Las herramientas de Azure Functions están disponibles como una CLI, conocida como Azure Functions Core Tools. + +1. Instala las herramientas principales de Azure Functions siguiendo las instrucciones en la [documentación de Azure Functions Core Tools](https://docs.microsoft.com/azure/azure-functions/functions-run-local?WT.mc_id=academic-17441-jabenn). + +1. Instala la extensión de Azure Functions para VS Code. Esta extensión proporciona soporte para crear, depurar y desplegar funciones de Azure. Consulta la [documentación de la extensión de Azure Functions](https://marketplace.visualstudio.com/items?WT.mc_id=academic-17441-jabenn&itemName=ms-azuretools.vscode-azurefunctions) para obtener instrucciones sobre cómo instalar esta extensión en VS Code. + +Cuando despliegues tu aplicación de Azure Functions en la nube, necesitará usar una pequeña cantidad de almacenamiento en la nube para guardar cosas como los archivos de la aplicación y los archivos de registro. Cuando ejecutes tu aplicación de funciones localmente, aún necesitarás conectarte al almacenamiento en la nube, pero en lugar de usar almacenamiento real en la nube, puedes usar un emulador de almacenamiento llamado [Azurite](https://github.com/Azure/Azurite). Este se ejecuta localmente pero actúa como almacenamiento en la nube. + +> 🎓 En Azure, el almacenamiento que utiliza Azure Functions es una Cuenta de Almacenamiento de Azure. Estas cuentas pueden almacenar archivos, blobs, datos en tablas o datos en colas. Puedes compartir una cuenta de almacenamiento entre muchas aplicaciones, como una aplicación de funciones y una aplicación web. + +1. Azurite es una aplicación Node.js, por lo que necesitarás instalar Node.js. Puedes encontrar las instrucciones de descarga e instalación en el [sitio web de Node.js](https://nodejs.org/). Si estás usando una Mac, también puedes instalarlo desde [Homebrew](https://formulae.brew.sh/formula/node). + +1. Instala Azurite usando el siguiente comando (`npm` es una herramienta que se instala cuando instalas Node.js): + + ```sh + npm install -g azurite + ``` + +1. Crea una carpeta llamada `azurite` para que Azurite la use para almacenar datos: + + ```sh + mkdir azurite + ``` + +1. Ejecuta Azurite, pasándole esta nueva carpeta: + + ```sh + azurite --location azurite + ``` + + El emulador de almacenamiento Azurite se iniciará y estará listo para que el runtime local de Functions se conecte. + + ```output + ➜ ~ azurite --location azurite + Azurite Blob service is starting at http://127.0.0.1:10000 + Azurite Blob service is successfully listening at http://127.0.0.1:10000 + Azurite Queue service is starting at http://127.0.0.1:10001 + Azurite Queue service is successfully listening at http://127.0.0.1:10001 + Azurite Table service is starting at http://127.0.0.1:10002 + Azurite Table service is successfully listening at http://127.0.0.1:10002 + ``` + +### Tarea - crear un proyecto de Azure Functions + +La CLI de Azure Functions puede usarse para crear una nueva aplicación de funciones. + +1. Crea una carpeta para tu aplicación de funciones y navega a ella. Llámala `soil-moisture-trigger`. + + ```sh + mkdir soil-moisture-trigger + cd soil-moisture-trigger + ``` + +1. Crea un entorno virtual de Python dentro de esta carpeta: + + ```sh + python3 -m venv .venv + ``` + +1. Activa el entorno virtual: + + * En Windows: + * Si estás usando el Command Prompt, o el Command Prompt a través de Windows Terminal, ejecuta: + + ```cmd + .venv\Scripts\activate.bat + ``` + + * Si estás usando PowerShell, ejecuta: + + ```powershell + .\.venv\Scripts\Activate.ps1 + ``` + + * En macOS o Linux, ejecuta: + + ```cmd + source ./.venv/bin/activate + ``` + + > 💁 Estos comandos deben ejecutarse desde la misma ubicación donde ejecutaste el comando para crear el entorno virtual. Nunca necesitarás navegar dentro de la carpeta `.venv`; siempre debes ejecutar el comando de activación y cualquier comando para instalar paquetes o ejecutar código desde la carpeta donde estabas cuando creaste el entorno virtual. + +1. Ejecuta el siguiente comando para crear una aplicación de funciones en esta carpeta: + + ```sh + func init --worker-runtime python soil-moisture-trigger + ``` + + Esto creará tres archivos dentro de la carpeta actual: + + * `host.json` - este documento JSON contiene configuraciones para tu aplicación de funciones. No necesitarás modificar estas configuraciones. + * `local.settings.json` - este documento JSON contiene configuraciones que tu aplicación usaría al ejecutarse localmente, como cadenas de conexión para tu IoT Hub. Estas configuraciones son solo locales y no deben agregarse al control de código fuente. Cuando despliegues la aplicación en la nube, estas configuraciones no se desplegarán; en su lugar, tus configuraciones se cargarán desde configuraciones de aplicación. Esto se cubrirá más adelante en esta lección. + * `requirements.txt` - este es un archivo de requisitos de [Pip](https://pip.pypa.io/en/stable/user_guide/#requirements-files) que contiene los paquetes de Pip necesarios para ejecutar tu aplicación de funciones. + +1. El archivo `local.settings.json` tiene una configuración para la cuenta de almacenamiento que la aplicación de funciones usará. Esto por defecto está vacío, por lo que necesita configurarse. Para conectarte al emulador de almacenamiento local Azurite, establece este valor en lo siguiente: + + ```json + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + ``` + +1. Instala los paquetes de Pip necesarios utilizando el archivo de requisitos: + + ```sh + pip install -r requirements.txt + ``` + + > 💁 Los paquetes de Pip requeridos deben estar en este archivo, para que cuando la aplicación de funciones se despliegue en la nube, el runtime pueda asegurarse de instalar los paquetes correctos. + +1. Para probar que todo está funcionando correctamente, puedes iniciar el runtime de Functions. Ejecuta el siguiente comando para hacerlo: + + ```sh + func start + ``` + + Verás que el runtime se inicia e informa que no ha encontrado funciones de trabajo (disparadores). + + ```output + (.venv) ➜ soil-moisture-trigger func start + Found Python version 3.9.1 (python3). + + Azure Functions Core Tools + Core Tools Version: 3.0.3442 Commit hash: 6bfab24b2743f8421475d996402c398d2fe4a9e0 (64-bit) + Function Runtime Version: 3.0.15417.0 + + [2021-05-05T01:24:46.795Z] No job functions found. + ``` +> ⚠️ Si recibes una notificación del firewall, concede acceso ya que la aplicación `func` necesita poder leer y escribir en tu red. +> ⚠️ Si estás utilizando macOS, es posible que aparezcan advertencias en la salida: +> +> ```output + > (.venv) ➜ soil-moisture-trigger func start + > Found Python version 3.9.1 (python3). + > + > Azure Functions Core Tools + > Core Tools Version: 3.0.3442 Commit hash: 6bfab24b2743f8421475d996402c398d2fe4a9e0 (64-bit) + > Function Runtime Version: 3.0.15417.0 + > + > [2021-06-16T08:18:28.315Z] Cannot create directory for shared memory usage: /dev/shm/AzureFunctions + > [2021-06-16T08:18:28.316Z] System.IO.FileSystem: Access to the path '/dev/shm/AzureFunctions' is denied. Operation not permitted. + > [2021-06-16T08:18:30.361Z] No job functions found. + > ``` +> +> Puedes ignorarlas siempre y cuando la aplicación de Functions se inicie correctamente y liste las funciones en ejecución. Como se menciona en [esta pregunta en Microsoft Docs Q&A](https://docs.microsoft.com/answers/questions/396617/azure-functions-core-tools-error-osx-devshmazurefu.html?WT.mc_id=academic-17441-jabenn), estas advertencias pueden ser ignoradas. + +1. Detén la aplicación de Functions presionando `ctrl+c`. + +1. Abre la carpeta actual en VS Code, ya sea abriendo VS Code y luego esta carpeta, o ejecutando el siguiente comando: + + ```sh + code . + ``` + + VS Code detectará tu proyecto de Functions y mostrará una notificación que dice: + + ```output + Detected an Azure Functions Project in folder "soil-moisture-trigger" that may have been created outside of + VS Code. Initialize for optimal use with VS Code? + ``` + + ![La notificación](../../../../../translated_images/vscode-azure-functions-init-notification.bd19b49229963edb5311fb3a79445ea469424759d2917ee2f2eb6f92d65d5086.es.png) + + Selecciona **Sí** en esta notificación. + +1. Asegúrate de que el entorno virtual de Python esté ejecutándose en la terminal de VS Code. Deténlo y reinícialo si es necesario. + +## Crear un disparador de eventos de IoT Hub + +La aplicación de Functions es el contenedor de tu código sin servidor. Para responder a eventos de IoT Hub, puedes agregar un disparador de IoT Hub a esta aplicación. Este disparador necesita conectarse al flujo de mensajes enviados al IoT Hub y responder a ellos. Para obtener este flujo de mensajes, tu disparador debe conectarse al *punto de conexión compatible con Event Hub* del IoT Hub. + +IoT Hub se basa en otro servicio de Azure llamado Azure Event Hubs. Event Hubs es un servicio que permite enviar y recibir mensajes, y IoT Hub amplía esto para agregar características específicas para dispositivos IoT. La forma en que te conectas para leer mensajes del IoT Hub es la misma que si estuvieras utilizando Event Hubs. + +✅ Investiga un poco: Lee la descripción general de Event Hubs en la [documentación de Azure Event Hubs](https://docs.microsoft.com/azure/event-hubs/event-hubs-about?WT.mc_id=academic-17441-jabenn). ¿Cómo se comparan las características básicas con IoT Hub? + +Para que un dispositivo IoT se conecte al IoT Hub, debe usar una clave secreta que garantice que solo los dispositivos permitidos puedan conectarse. Lo mismo aplica al conectarse para leer mensajes; tu código necesitará una cadena de conexión que contenga una clave secreta, junto con los detalles del IoT Hub. + +> 💁 La cadena de conexión predeterminada que obtienes tiene permisos de **iothubowner**, lo que otorga a cualquier código que la use permisos completos en el IoT Hub. Idealmente, deberías conectarte con el nivel más bajo de permisos necesarios. Esto se cubrirá en la próxima lección. + +Una vez que tu disparador se haya conectado, el código dentro de la función se ejecutará para cada mensaje enviado al IoT Hub, independientemente del dispositivo que lo haya enviado. El disparador recibirá el mensaje como un parámetro. + +### Tarea - obtener la cadena de conexión del punto de conexión compatible con Event Hub + +1. Desde la terminal de VS Code, ejecuta el siguiente comando para obtener la cadena de conexión del punto de conexión compatible con Event Hub del IoT Hub: + + ```sh + az iot hub connection-string show --default-eventhub \ + --output table \ + --hub-name + ``` + + Sustituye `` por el nombre que usaste para tu IoT Hub. + +1. En VS Code, abre el archivo `local.settings.json`. Agrega el siguiente valor adicional dentro de la sección `Values`: + + ```json + "IOT_HUB_CONNECTION_STRING": "" + ``` + + Sustituye `` por el valor del paso anterior. Necesitarás agregar una coma después de la línea anterior para que sea un JSON válido. + +### Tarea - crear un disparador de eventos + +Ahora estás listo para crear el disparador de eventos. + +1. Desde la terminal de VS Code, ejecuta el siguiente comando desde dentro de la carpeta `soil-moisture-trigger`: + + ```sh + func new --name iot-hub-trigger --template "Azure Event Hub trigger" + ``` + + Esto crea una nueva función llamada `iot-hub-trigger`. El disparador se conectará al punto de conexión compatible con Event Hub en el IoT Hub, por lo que puedes usar un disparador de Event Hub. No existe un disparador específico para IoT Hub. + +Esto creará una carpeta dentro de la carpeta `soil-moisture-trigger` llamada `iot-hub-trigger` que contiene esta función. Esta carpeta tendrá los siguientes archivos: + +* `__init__.py` - este es el archivo de código Python que contiene el disparador, utilizando la convención estándar de nombres de archivos Python para convertir esta carpeta en un módulo de Python. + + Este archivo contendrá el siguiente código: + + ```python + import logging + + import azure.functions as func + + + def main(event: func.EventHubEvent): + logging.info('Python EventHub trigger processed an event: %s', + event.get_body().decode('utf-8')) + ``` + + El núcleo del disparador es la función `main`. Es esta función la que se llama con los eventos del IoT Hub. Esta función tiene un parámetro llamado `event` que contiene un `EventHubEvent`. Cada vez que se envía un mensaje al IoT Hub, esta función se llama pasando ese mensaje como el `event`, junto con propiedades que son las mismas que las anotaciones que viste en la última lección. + + El núcleo de esta función registra el evento. + +* `function.json` - este archivo contiene la configuración del disparador. La configuración principal está en una sección llamada `bindings`. Un binding es el término para una conexión entre Azure Functions y otros servicios de Azure. Esta función tiene un binding de entrada a un Event Hub: se conecta a un Event Hub y recibe datos. + + > 💁 También puedes tener bindings de salida para que la salida de una función se envíe a otro servicio. Por ejemplo, podrías agregar un binding de salida a una base de datos y devolver el evento del IoT Hub desde la función, y este se insertará automáticamente en la base de datos. + + ✅ Investiga un poco: Lee sobre los bindings en la [documentación de conceptos de disparadores y bindings de Azure Functions](https://docs.microsoft.com/azure/azure-functions/functions-triggers-bindings?WT.mc_id=academic-17441-jabenn&tabs=python). + + La sección `bindings` incluye la configuración del binding. Los valores de interés son: + + * `"type": "eventHubTrigger"` - esto indica que la función necesita escuchar eventos de un Event Hub. + * `"name": "events"` - este es el nombre del parámetro para los eventos del Event Hub. Esto coincide con el nombre del parámetro en la función `main` en el código Python. + * `"direction": "in"` - este es un binding de entrada; los datos del Event Hub ingresan a la función. + * `"connection": ""` - esto define el nombre de la configuración para leer la cadena de conexión. Al ejecutarse localmente, leerá esta configuración del archivo `local.settings.json`. + + > 💁 La cadena de conexión no puede almacenarse en el archivo `function.json`; debe leerse desde la configuración. Esto es para evitar que expongas accidentalmente tu cadena de conexión. + +1. Debido a [un error en la plantilla de Azure Functions](https://github.com/Azure/azure-functions-templates/issues/1250), el archivo `function.json` tiene un valor incorrecto para el campo `cardinality`. Actualiza este campo de `many` a `one`: + + ```json + "cardinality": "one", + ``` + +1. Actualiza el valor de `"connection"` en el archivo `function.json` para que apunte al nuevo valor que agregaste en el archivo `local.settings.json`: + + ```json + "connection": "IOT_HUB_CONNECTION_STRING", + ``` + + > 💁 Recuerda: esto debe apuntar a la configuración, no contener la cadena de conexión real. + +1. La cadena de conexión contiene el valor `eventHubName`, por lo que el valor para esto en el archivo `function.json` debe dejarse vacío. Actualiza este valor a una cadena vacía: + + ```json + "eventHubName": "", + ``` + +### Tarea - ejecutar el disparador de eventos + +1. Asegúrate de que no estás ejecutando el monitor de eventos de IoT Hub. Si este está en ejecución al mismo tiempo que la aplicación de Functions, la aplicación de Functions no podrá conectarse y consumir eventos. + + > 💁 Varias aplicaciones pueden conectarse a los puntos de conexión de IoT Hub utilizando diferentes *grupos de consumidores*. Esto se cubrirá en una lección posterior. + +1. Para ejecutar la aplicación de Functions, ejecuta el siguiente comando desde la terminal de VS Code: + + ```sh + func start + ``` + + La aplicación de Functions se iniciará y descubrirá la función `iot-hub-trigger`. Luego procesará cualquier evento que ya se haya enviado al IoT Hub en el último día. + + ```output + (.venv) ➜ soil-moisture-trigger func start + Found Python version 3.9.1 (python3). + + Azure Functions Core Tools + Core Tools Version: 3.0.3442 Commit hash: 6bfab24b2743f8421475d996402c398d2fe4a9e0 (64-bit) + Function Runtime Version: 3.0.15417.0 + + Functions: + + iot-hub-trigger: eventHubTrigger + + For detailed output, run func with --verbose flag. + [2021-05-05T02:44:07.517Z] Worker process started and initialized. + [2021-05-05T02:44:09.202Z] Executing 'Functions.iot-hub-trigger' (Reason='(null)', Id=802803a5-eae9-4401-a1f4-176631456ce4) + [2021-05-05T02:44:09.205Z] Trigger Details: PartitionId: 0, Offset: 1011240-1011632, EnqueueTimeUtc: 2021-05-04T19:04:04.2030000Z-2021-05-04T19:04:04.3900000Z, SequenceNumber: 2546-2547, Count: 2 + [2021-05-05T02:44:09.352Z] Python EventHub trigger processed an event: {"soil_moisture":628} + [2021-05-05T02:44:09.354Z] Python EventHub trigger processed an event: {"soil_moisture":624} + [2021-05-05T02:44:09.395Z] Executed 'Functions.iot-hub-trigger' (Succeeded, Id=802803a5-eae9-4401-a1f4-176631456ce4, Duration=245ms) + ``` + + Cada llamada a la función estará rodeada por un bloque `Executing 'Functions.iot-hub-trigger'`/`Executed 'Functions.iot-hub-trigger'` en la salida, para que puedas ver cuántos mensajes se procesaron en cada llamada a la función. + +1. Asegúrate de que tu dispositivo IoT esté en funcionamiento. Verás nuevos mensajes de humedad del suelo apareciendo en la aplicación de Functions. + +1. Detén y reinicia la aplicación de Functions. Verás que no procesará mensajes anteriores nuevamente, solo procesará nuevos mensajes. + +> 💁 VS Code también admite la depuración de tus Functions. Puedes establecer puntos de interrupción haciendo clic en el borde al inicio de cada línea de código, colocando el cursor en una línea de código y seleccionando *Ejecutar -> Alternar punto de interrupción*, o presionando `F9`. Puedes iniciar el depurador seleccionando *Ejecutar -> Iniciar depuración*, presionando `F5`, o seleccionando el panel *Ejecutar y depurar* y haciendo clic en el botón **Iniciar depuración**. Al hacerlo, puedes ver los detalles de los eventos que se están procesando. + +#### Resolución de problemas + +* Si obtienes el siguiente error: + + ```output + The listener for function 'Functions.iot-hub-trigger' was unable to start. Microsoft.WindowsAzure.Storage: Connection refused. System.Net.Http: Connection refused. System.Private.CoreLib: Connection refused. + ``` + + Verifica que Azurite esté en ejecución y que hayas configurado el `AzureWebJobsStorage` en el archivo `local.settings.json` como `UseDevelopmentStorage=true`. + +* Si obtienes el siguiente error: + + ```output + System.Private.CoreLib: Exception while executing function: Functions.iot-hub-trigger. System.Private.CoreLib: Result: Failure Exception: AttributeError: 'list' object has no attribute 'get_body' + ``` + + Verifica que hayas configurado el `cardinality` en el archivo `function.json` como `one`. + +* Si obtienes el siguiente error: + + ```output + Azure.Messaging.EventHubs: The path to an Event Hub may be specified as part of the connection string or as a separate value, but not both. Please verify that your connection string does not have the `EntityPath` token if you are passing an explicit Event Hub name. (Parameter 'connectionString'). + ``` + + Verifica que hayas configurado el `eventHubName` en el archivo `function.json` como una cadena vacía. + +## Enviar solicitudes de método directo desde código sin servidor + +Hasta ahora, tu aplicación de Functions está escuchando mensajes del IoT Hub utilizando el punto de conexión compatible con Event Hub. Ahora necesitas enviar comandos al dispositivo IoT. Esto se hace utilizando una conexión diferente al IoT Hub a través del *Registry Manager*. El Registry Manager es una herramienta que te permite ver qué dispositivos están registrados en el IoT Hub y comunicarte con esos dispositivos enviando mensajes de nube a dispositivo, solicitudes de método directo o actualizando el dispositivo gemelo. También puedes usarlo para registrar, actualizar o eliminar dispositivos IoT del IoT Hub. + +Para conectarte al Registry Manager, necesitas una cadena de conexión. + +### Tarea - obtener la cadena de conexión del Registry Manager + +1. Para obtener la cadena de conexión, ejecuta el siguiente comando: + + ```sh + az iot hub connection-string show --policy-name service \ + --output table \ + --hub-name + ``` + + Sustituye `` por el nombre que usaste para tu IoT Hub. + + La cadena de conexión se solicita para la política *ServiceConnect* utilizando el parámetro `--policy-name service`. Cuando solicitas una cadena de conexión, puedes especificar qué permisos permitirá esa cadena de conexión. La política ServiceConnect permite que tu código se conecte y envíe mensajes a dispositivos IoT. + + ✅ Investiga un poco: Lee sobre las diferentes políticas en la [documentación de permisos de IoT Hub](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-security#iot-hub-permissions?WT.mc_id=academic-17441-jabenn). + +1. En VS Code, abre el archivo `local.settings.json`. Agrega el siguiente valor adicional dentro de la sección `Values`: + + ```json + "REGISTRY_MANAGER_CONNECTION_STRING": "" + ``` + + Sustituye `` por el valor del paso anterior. Necesitarás agregar una coma después de la línea anterior para que sea un JSON válido. + +### Tarea - enviar una solicitud de método directo a un dispositivo + +1. El SDK para el Registry Manager está disponible a través de un paquete Pip. Agrega la siguiente línea al archivo `requirements.txt` para agregar la dependencia de este paquete: + + ```sh + azure-iot-hub + ``` + +1. Asegúrate de que la terminal de VS Code tenga el entorno virtual activado y ejecuta el siguiente comando para instalar los paquetes Pip: + + ```sh + pip install -r requirements.txt + ``` + +1. Agrega las siguientes importaciones al archivo `__init__.py`: + + ```python + import json + import os + from azure.iot.hub import IoTHubRegistryManager + from azure.iot.hub.models import CloudToDeviceMethod + ``` + + Esto importa algunas bibliotecas del sistema, así como las bibliotecas para interactuar con el Registry Manager y enviar solicitudes de método directo. + +1. Elimina el código dentro del método `main`, pero conserva el método en sí. + +1. En el método `main`, agrega el siguiente código: + + ```python + body = json.loads(event.get_body().decode('utf-8')) + device_id = event.iothub_metadata['connection-device-id'] + + logging.info(f'Received message: {body} from {device_id}') + ``` + + Este código extrae el cuerpo del evento que contiene el mensaje JSON enviado por el dispositivo IoT. + + Luego obtiene el ID del dispositivo de las anotaciones pasadas con el mensaje. El cuerpo del evento contiene el mensaje enviado como telemetría, el diccionario `iothub_metadata` contiene propiedades establecidas por el IoT Hub, como el ID del dispositivo del remitente y la hora en que se envió el mensaje. + + Esta información luego se registra. Verás este registro en la terminal cuando ejecutes la aplicación de Functions localmente. + +1. Debajo de esto, agrega el siguiente código: + + ```python + soil_moisture = body['soil_moisture'] + + if soil_moisture > 450: + direct_method = CloudToDeviceMethod(method_name='relay_on', payload='{}') + else: + direct_method = CloudToDeviceMethod(method_name='relay_off', payload='{}') + ``` + + Este código obtiene la humedad del suelo del mensaje. Luego verifica la humedad del suelo y, dependiendo del valor, crea una clase auxiliar para la solicitud de método directo para el método `relay_on` o `relay_off`. La solicitud del método no necesita una carga útil, por lo que se envía un documento JSON vacío. + +1. Debajo de esto, agrega el siguiente código: + + ```python + logging.info(f'Sending direct method request for {direct_method.method_name} for device {device_id}') + + registry_manager_connection_string = os.environ['REGISTRY_MANAGER_CONNECTION_STRING'] + registry_manager = IoTHubRegistryManager(registry_manager_connection_string) + ``` +Este código carga el `REGISTRY_MANAGER_CONNECTION_STRING` desde el archivo `local.settings.json`. Los valores en este archivo están disponibles como variables de entorno, y se pueden leer utilizando la función `os.environ`, una función que devuelve un diccionario con todas las variables de entorno. + +> 💁 Cuando este código se despliega en la nube, los valores en el archivo `local.settings.json` se configurarán como *Application Settings*, y se podrán leer desde las variables de entorno. + +El código luego crea una instancia de la clase auxiliar Registry Manager utilizando la cadena de conexión. + +1. Debajo de esto, agrega el siguiente código: + + ```python + registry_manager.invoke_device_method(device_id, direct_method) + + logging.info('Direct method request sent!') + ``` + + Este código indica al registry manager que envíe la solicitud de método directo al dispositivo que envió la telemetría. + + > 💁 En las versiones de la aplicación que creaste en lecciones anteriores utilizando MQTT, los comandos de control del relé se enviaban a todos los dispositivos. El código asumía que solo tendrías un dispositivo. Esta versión del código envía la solicitud de método a un único dispositivo, por lo que funcionaría si tuvieras múltiples configuraciones de sensores de humedad y relés, enviando la solicitud de método directo al dispositivo correcto. + +1. Ejecuta la aplicación de Functions y asegúrate de que tu dispositivo IoT esté enviando datos. Verás los mensajes siendo procesados y las solicitudes de método directo siendo enviadas. Mueve el sensor de humedad del suelo dentro y fuera del suelo para ver cómo cambian los valores y el relé se enciende y apaga. + +> 💁 Puedes encontrar este código en la carpeta [code/functions](../../../../../2-farm/lessons/5-migrate-application-to-the-cloud/code/functions). + +## Despliega tu código sin servidor en la nube + +Tu código ya está funcionando localmente, así que el siguiente paso es desplegar la aplicación de Functions en la nube. + +### Tarea - crear los recursos en la nube + +Tu aplicación de Functions necesita ser desplegada en un recurso de Functions App en Azure, dentro del grupo de recursos que creaste para tu IoT Hub. También necesitarás una cuenta de almacenamiento creada en Azure para reemplazar la emulada que tienes funcionando localmente. + +1. Ejecuta el siguiente comando para crear una cuenta de almacenamiento: + + ```sh + az storage account create --resource-group soil-moisture-sensor \ + --sku Standard_LRS \ + --name + ``` + + Sustituye `` por un nombre para tu cuenta de almacenamiento. Este debe ser único a nivel global, ya que forma parte de la URL utilizada para acceder a la cuenta de almacenamiento. Solo puedes usar letras minúsculas y números para este nombre, sin otros caracteres, y está limitado a 24 caracteres. Usa algo como `sms` y agrega un identificador único al final, como algunas palabras aleatorias o tu nombre. + + La opción `--sku Standard_LRS` selecciona el nivel de precios, eligiendo la cuenta general de menor costo. No hay un nivel gratuito de almacenamiento, y pagas por lo que usas. Los costos son relativamente bajos, siendo el almacenamiento más caro menos de US$0.05 por mes por gigabyte almacenado. + + ✅ Lee más sobre precios en la [página de precios de Azure Storage Account](https://azure.microsoft.com/pricing/details/storage/?WT.mc_id=academic-17441-jabenn) + +1. Ejecuta el siguiente comando para crear una Function App: + + ```sh + az functionapp create --resource-group soil-moisture-sensor \ + --runtime python \ + --functions-version 3 \ + --os-type Linux \ + --consumption-plan-location \ + --storage-account \ + --name + ``` + + Sustituye `` por la ubicación que usaste al crear el grupo de recursos en la lección anterior. + + Sustituye `` por el nombre de la cuenta de almacenamiento que creaste en el paso anterior. + + Sustituye `` por un nombre único para tu Function App. Este debe ser único a nivel global, ya que forma parte de una URL que puede ser utilizada para acceder a la Function App. Usa algo como `soil-moisture-sensor-` y agrega un identificador único al final, como algunas palabras aleatorias o tu nombre. + + La opción `--functions-version 3` establece la versión de Azure Functions a utilizar. La versión 3 es la más reciente. + + La opción `--os-type Linux` indica al runtime de Functions que use Linux como sistema operativo para alojar estas funciones. Las funciones pueden alojarse en Linux o Windows, dependiendo del lenguaje de programación utilizado. Las aplicaciones en Python solo son compatibles con Linux. + +### Tarea - subir tus configuraciones de aplicación + +Cuando desarrollaste tu Function App, almacenaste algunas configuraciones en el archivo `local.settings.json` para las cadenas de conexión de tu IoT Hub. Estas deben ser escritas en las Application Settings de tu Function App en Azure para que puedan ser utilizadas por tu código. + +> 🎓 El archivo `local.settings.json` es solo para configuraciones de desarrollo local, y no debe ser incluido en el control de código fuente, como GitHub. Cuando se despliega en la nube, se utilizan las Application Settings. Las Application Settings son pares clave/valor alojados en la nube y se leen desde las variables de entorno, ya sea en tu código o por el runtime al conectar tu código con IoT Hub. + +1. Ejecuta el siguiente comando para establecer la configuración `IOT_HUB_CONNECTION_STRING` en las Application Settings de la Function App: + + ```sh + az functionapp config appsettings set --resource-group soil-moisture-sensor \ + --name \ + --settings "IOT_HUB_CONNECTION_STRING=" + ``` + + Sustituye `` por el nombre que usaste para tu Function App. + + Sustituye `` por el valor de `IOT_HUB_CONNECTION_STRING` de tu archivo `local.settings.json`. + +1. Repite el paso anterior, pero establece el valor de `REGISTRY_MANAGER_CONNECTION_STRING` con el valor correspondiente de tu archivo `local.settings.json`. + +Cuando ejecutes estos comandos, también se mostrará una lista de todas las Application Settings para la Function App. Puedes usar esto para verificar que tus valores estén configurados correctamente. + +> 💁 Verás un valor ya configurado para `AzureWebJobsStorage`. En tu archivo `local.settings.json`, este se configuró con un valor para usar el emulador de almacenamiento local. Cuando creaste la Function App, pasaste la cuenta de almacenamiento como un parámetro, y esto se configura automáticamente en esta configuración. + +### Tarea - despliega tu Function App en la nube + +Ahora que la Function App está lista, tu código puede ser desplegado. + +1. Ejecuta el siguiente comando desde el terminal de VS Code para publicar tu Function App: + + ```sh + func azure functionapp publish + ``` + + Sustituye `` por el nombre que usaste para tu Function App. + +El código será empaquetado y enviado a la Function App, donde será desplegado y comenzará a ejecutarse. Habrá mucha salida en la consola, terminando con la confirmación del despliegue y una lista de las funciones desplegadas. En este caso, la lista solo contendrá el trigger. + +```output +Deployment successful. +Remote build succeeded! +Syncing triggers... +Functions in soil-moisture-sensor: + iot-hub-trigger - [eventHubTrigger] +``` + +Asegúrate de que tu dispositivo IoT esté funcionando. Cambia los niveles de humedad ajustando la humedad del suelo o moviendo el sensor dentro y fuera del suelo. Verás el relé encenderse y apagarse a medida que cambian los niveles de humedad del suelo. + +--- + +## 🚀 Desafío + +En la lección anterior, gestionaste el tiempo del relé cancelando la suscripción a los mensajes MQTT mientras el relé estaba encendido y durante un breve período después de que se apagaba. No puedes usar este método aquí: no puedes cancelar la suscripción a tu trigger de IoT Hub. + +Piensa en diferentes formas en las que podrías manejar esto en tu Function App. + +## Cuestionario post-lección + +[Cuestionario post-lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/18) + +## Revisión y autoestudio + +* Lee sobre computación sin servidor en la [página de computación sin servidor en Wikipedia](https://wikipedia.org/wiki/Serverless_computing) +* Lee sobre el uso de serverless en Azure, incluyendo algunos ejemplos adicionales en el [blog de Azure sobre necesidades IoT sin servidor](https://azure.microsoft.com/blog/go-serverless-for-your-iot-needs/?WT.mc_id=academic-17441-jabenn) +* Aprende más sobre Azure Functions en el [canal de YouTube de Azure Functions](https://www.youtube.com/c/AzureFunctions) + +## Tarea + +[Agregar control manual del relé](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/5-migrate-application-to-the-cloud/assignment.md b/translations/es/2-farm/lessons/5-migrate-application-to-the-cloud/assignment.md new file mode 100644 index 00000000..508e045e --- /dev/null +++ b/translations/es/2-farm/lessons/5-migrate-application-to-the-cloud/assignment.md @@ -0,0 +1,70 @@ + +# Agregar control manual del relé + +## Instrucciones + +El código sin servidor puede ser activado por muchas cosas diferentes, incluidas las solicitudes HTTP. Puedes usar disparadores HTTP para agregar un control manual a tu relé, permitiendo que alguien encienda o apague el relé desde una solicitud web. + +Para esta tarea, necesitas agregar dos disparadores HTTP a tu Functions App para encender y apagar el relé, reutilizando lo que has aprendido en esta lección para enviar comandos al dispositivo. + +Algunas pistas: + +* Puedes agregar un disparador HTTP a tu Functions App existente con el siguiente comando: + + ```sh + func new --name --template "HTTP trigger" + ``` + + Reemplaza `` con el nombre de tu disparador HTTP. Usa algo como `relay_on` y `relay_off`. + +* Los disparadores HTTP pueden tener control de acceso. Por defecto, requieren que se pase una clave API específica de la función con la URL para ejecutarse. Para esta tarea, puedes eliminar esta restricción para que cualquiera pueda ejecutar la función. Para hacerlo, actualiza la configuración `authLevel` en el archivo `function.json` de los disparadores HTTP a lo siguiente: + + ```json + "authLevel": "anonymous" + ``` + + > 💁 Puedes leer más sobre este control de acceso en la [documentación de claves de acceso de funciones](https://docs.microsoft.com/azure/azure-functions/functions-bindings-http-webhook-trigger?WT.mc_id=academic-17441-jabenn#authorization-keys). + +* Los disparadores HTTP, por defecto, soportan solicitudes GET y POST. Esto significa que puedes llamarlos usando tu navegador web, ya que los navegadores web realizan solicitudes GET. + + Cuando ejecutes tu Functions App localmente, verás la URL del disparador: + + ```output + Functions: + + relay_off: [GET,POST] http://localhost:7071/api/relay_off + + relay_on: [GET,POST] http://localhost:7071/api/relay_on + + iot-hub-trigger: eventHubTrigger + ``` + + Pega la URL en tu navegador y presiona `return`, o `Ctrl+click` (`Cmd+click` en macOS) en el enlace en la ventana del terminal en VS Code para abrirlo en tu navegador predeterminado. Esto ejecutará el disparador. + + > 💁 Nota que la URL tiene `/api` en ella: los disparadores HTTP están, por defecto, en el subdominio `api`. + +* Cuando despliegues la Functions App, la URL del disparador HTTP será: + + `https://.azurewebsites.net/api/` + + Donde `` es el nombre de tu Functions App, y `` es el nombre de tu disparador. + +## Rúbrica + +| Criterios | Ejemplar | Adecuado | Necesita Mejorar | +| --------- | -------- | -------- | ---------------- | +| Crear disparadores HTTP | Creó 2 disparadores para encender y apagar el relé, con nombres apropiados | Creó un disparador con un nombre apropiado | No pudo crear ningún disparador | +| Controlar el relé desde los disparadores HTTP | Pudo conectar ambos disparadores al IoT Hub y controlar el relé adecuadamente | Pudo conectar un disparador al IoT Hub y controlar el relé adecuadamente | No pudo conectar los disparadores al IoT Hub | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de ningún malentendido o interpretación errónea que surja del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/6-keep-your-plant-secure/README.md b/translations/es/2-farm/lessons/6-keep-your-plant-secure/README.md new file mode 100644 index 00000000..cff25788 --- /dev/null +++ b/translations/es/2-farm/lessons/6-keep-your-plant-secure/README.md @@ -0,0 +1,245 @@ + +# Mantén tu planta segura + +![Un resumen visual de esta lección](../../../../../translated_images/lesson-10.829c86b80b9403bb770929ee553a1d293afe50dc23121aaf9be144673ae012cc.es.jpg) + +> Dibujo por [Nitya Narasimhan](https://github.com/nitya). Haz clic en la imagen para verla en mayor tamaño. + +## Cuestionario previo a la lección + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/19) + +## Introducción + +En las últimas lecciones has creado un dispositivo IoT para monitorear el suelo y lo has conectado a la nube. Pero, ¿qué pasaría si hackers que trabajan para un agricultor rival lograran tomar el control de tus dispositivos IoT? ¿Y si enviaran lecturas falsas de alta humedad del suelo para que tus plantas nunca se rieguen, o activaran tu sistema de riego constantemente, matando tus plantas por exceso de agua y generándote un gran gasto en agua? + +En esta lección aprenderás sobre cómo proteger los dispositivos IoT. Como esta es la última lección de este proyecto, también aprenderás a limpiar tus recursos en la nube, reduciendo posibles costos. + +En esta lección cubriremos: + +* [¿Por qué necesitas proteger los dispositivos IoT?](../../../../../2-farm/lessons/6-keep-your-plant-secure) +* [Criptografía](../../../../../2-farm/lessons/6-keep-your-plant-secure) +* [Protege tus dispositivos IoT](../../../../../2-farm/lessons/6-keep-your-plant-secure) +* [Genera y utiliza un certificado X.509](../../../../../2-farm/lessons/6-keep-your-plant-secure) + +> 🗑 Esta es la última lección de este proyecto, así que después de completar esta lección y la tarea, no olvides limpiar tus servicios en la nube. Necesitarás los servicios para completar la tarea, así que asegúrate de terminarla primero. +> +> Consulta [la guía para limpiar tu proyecto](../../../clean-up.md) si necesitas instrucciones sobre cómo hacerlo. + +## ¿Por qué necesitas proteger los dispositivos IoT? + +La seguridad en IoT implica garantizar que solo los dispositivos esperados puedan conectarse a tu servicio IoT en la nube y enviarle telemetría, y que solo tu servicio en la nube pueda enviar comandos a tus dispositivos. Los datos de IoT también pueden ser personales, incluyendo datos médicos o íntimos, por lo que toda tu aplicación debe considerar la seguridad para evitar que estos datos se filtren. + +Si tu aplicación IoT no es segura, existen varios riesgos: + +* Un dispositivo falso podría enviar datos incorrectos, haciendo que tu aplicación responda de manera incorrecta. Por ejemplo, podrían enviar lecturas constantes de alta humedad del suelo, lo que significaría que tu sistema de riego nunca se active y tus plantas mueran por falta de agua. +* Usuarios no autorizados podrían leer datos de los dispositivos IoT, incluyendo datos personales o críticos para el negocio. +* Hackers podrían enviar comandos para controlar un dispositivo de una manera que podría causar daños al dispositivo o al hardware conectado. +* Al conectarse a un dispositivo IoT, los hackers podrían usarlo para acceder a redes adicionales y obtener acceso a sistemas privados. +* Usuarios malintencionados podrían acceder a datos personales y utilizarlos para chantaje. + +Estos son escenarios del mundo real y ocurren todo el tiempo. Algunos ejemplos se mencionaron en lecciones anteriores, pero aquí hay algunos más: + +* En 2018, hackers usaron un punto de acceso WiFi abierto en un termostato de pecera para acceder a la red de un casino y robar datos. [The Hacker News - Casino Gets Hacked Through Its Internet-Connected Fish Tank Thermometer](https://thehackernews.com/2018/04/iot-hacking-thermometer.html) +* En 2016, el botnet Mirai lanzó un ataque de denegación de servicio contra Dyn, un proveedor de servicios de Internet, dejando fuera de servicio grandes partes de Internet. Este botnet utilizó malware para conectarse a dispositivos IoT como grabadoras de video y cámaras que usaban nombres de usuario y contraseñas predeterminados, y desde allí lanzó el ataque. [The Guardian - DDoS attack that disrupted internet was largest of its kind in history, experts say](https://www.theguardian.com/technology/2016/oct/26/ddos-attack-dyn-mirai-botnet) +* Spiral Toys tenía una base de datos de usuarios de sus juguetes conectados CloudPets disponible públicamente en Internet. [Troy Hunt - Data from connected CloudPets teddy bears leaked and ransomed, exposing kids' voice messages](https://www.troyhunt.com/data-from-connected-cloudpets-teddy-bears-leaked-and-ransomed-exposing-kids-voice-messages/). +* Strava etiquetaba a corredores que pasaban cerca y mostraba sus rutas, permitiendo a extraños ver dónde vivían. [Kim Komndo - Fitness app could lead a stranger right to your home — change this setting](https://www.komando.com/security-privacy/strava-fitness-app-privacy/755349/). + +✅ Investiga: Busca más ejemplos de hacks y brechas de datos en IoT, especialmente con objetos personales como cepillos de dientes o básculas conectadas a Internet. Reflexiona sobre el impacto que estos hacks podrían tener en las víctimas o clientes. + +> 💁 La seguridad es un tema enorme, y esta lección solo tocará algunos de los conceptos básicos sobre la conexión de tu dispositivo a la nube. Otros temas que no se cubrirán incluyen el monitoreo de cambios en los datos durante la transmisión, el hackeo directo de dispositivos o los cambios en las configuraciones de los dispositivos. El hackeo de IoT es una amenaza tan grande que se han desarrollado herramientas como [Azure Defender for IoT](https://azure.microsoft.com/services/azure-defender-for-iot/?WT.mc_id=academic-17441-jabenn). Estas herramientas son similares a los antivirus y herramientas de seguridad que podrías tener en tu computadora, pero diseñadas para dispositivos IoT pequeños y de bajo consumo. + +## Criptografía + +Cuando un dispositivo se conecta a un servicio IoT, utiliza un ID para identificarse. El problema es que este ID puede ser clonado: un hacker podría configurar un dispositivo malicioso que use el mismo ID que un dispositivo real pero que envíe datos falsos. + +![Tanto dispositivos válidos como maliciosos podrían usar el mismo ID para enviar telemetría](../../../../../translated_images/iot-device-and-hacked-device-connecting.e0671675df74d6d99eb1dedb5a670e606f698efa6202b1ad4c8ae548db299cc6.es.png) + +La solución a esto es convertir los datos enviados en un formato codificado, utilizando un valor conocido solo por el dispositivo y la nube para codificar los datos. Este proceso se llama *encriptación*, y el valor utilizado para encriptar los datos se llama *clave de encriptación*. + +![Si se usa encriptación, solo se aceptarán mensajes encriptados; los demás serán rechazados](../../../../../translated_images/iot-device-and-hacked-device-connecting-encryption.5941aff601fc978f979e46f2849b573564eeb4a4dc5b52f669f62745397492fb.es.png) + +El servicio en la nube puede luego convertir los datos a un formato legible, utilizando un proceso llamado *desencriptación*, ya sea con la misma clave de encriptación o con una *clave de desencriptación*. Si el mensaje encriptado no puede ser desencriptado con la clave, el dispositivo ha sido hackeado y el mensaje es rechazado. + +La técnica para realizar la encriptación y desencriptación se llama *criptografía*. + +### Criptografía temprana + +Los primeros tipos de criptografía fueron los cifrados por sustitución, que datan de hace 3,500 años. Estos cifrados implican sustituir una letra por otra. Por ejemplo, el [cifrado César](https://wikipedia.org/wiki/Caesar_cipher) implica desplazar el alfabeto por una cantidad definida, conocida solo por el remitente y el destinatario del mensaje encriptado. + +El [cifrado Vigenère](https://wikipedia.org/wiki/Vigenère_cipher) llevó esto más allá al usar palabras para encriptar texto, de modo que cada letra en el texto original se desplazaba por una cantidad diferente, en lugar de siempre desplazarse por el mismo número de letras. + +La criptografía se utilizó para una amplia gama de propósitos, como proteger recetas de esmaltes de cerámica en la antigua Mesopotamia, escribir notas de amor secretas en India o mantener en secreto hechizos mágicos en el antiguo Egipto. + +### Criptografía moderna + +La criptografía moderna es mucho más avanzada, lo que la hace más difícil de descifrar que los métodos antiguos. Utiliza matemáticas complejas para encriptar datos con demasiadas claves posibles como para que un ataque de fuerza bruta sea viable. + +La criptografía se utiliza de muchas maneras para comunicaciones seguras. Si estás leyendo esta página en GitHub, notarás que la dirección del sitio web comienza con *HTTPS*, lo que significa que la comunicación entre tu navegador y los servidores web de GitHub está encriptada. Si alguien pudiera leer el tráfico de Internet entre tu navegador y GitHub, no podría entender los datos porque están encriptados. Incluso tu computadora podría encriptar todos los datos en tu disco duro para que, si alguien lo roba, no pueda leer tus datos sin tu contraseña. + +> 🎓 HTTPS significa Protocolo de Transferencia de Hipertexto **Seguro** + +Desafortunadamente, no todo es seguro. Algunos dispositivos no tienen seguridad, otros están protegidos con claves fáciles de descifrar, o incluso todos los dispositivos del mismo tipo usan la misma clave. Ha habido casos de dispositivos IoT muy personales que tienen la misma contraseña para conectarse a ellos a través de WiFi o Bluetooth. Si puedes conectarte a tu propio dispositivo, podrías conectarte al de otra persona. Una vez conectado, podrías acceder a datos muy privados o controlar su dispositivo. + +> 💁 A pesar de las complejidades de la criptografía moderna y las afirmaciones de que romper la encriptación puede tomar miles de millones de años, el auge de la computación cuántica ha llevado a la posibilidad de romper toda la encriptación conocida en un tiempo muy corto. + +### Claves simétricas y asimétricas + +La encriptación puede ser de dos tipos: simétrica y asimétrica. + +La encriptación **simétrica** utiliza la misma clave para encriptar y desencriptar los datos. Tanto el remitente como el receptor necesitan conocer la misma clave. Este es el tipo menos seguro, ya que la clave debe compartirse de alguna manera. Para que un remitente envíe un mensaje encriptado a un receptor, el remitente primero podría tener que enviarle la clave al receptor. + +![La encriptación simétrica utiliza la misma clave para encriptar y desencriptar un mensaje](../../../../../translated_images/send-message-symmetric-key.a2e8ad0d495896ffcdf15d25bb4491c695a5cb851457b359fb0f0c89d67707c9.es.png) + +Si la clave es robada durante la transmisión, o si el remitente o receptor son hackeados y la clave es encontrada, la encriptación puede ser descifrada. + +![La encriptación simétrica solo es segura si un hacker no obtiene la clave; si lo hace, puede interceptar y desencriptar el mensaje](../../../../../translated_images/send-message-symmetric-key-hacker.e7cb53db1707adfb1486a8144060cb76435fe8dbdede8cecc09e7d15b2d9a251.es.png) + +La encriptación **asimétrica** utiliza 2 claves: una clave de encriptación y una clave de desencriptación, conocidas como un par de claves pública/privada. La clave pública se utiliza para encriptar el mensaje, pero no puede usarse para desencriptarlo; la clave privada se utiliza para desencriptar el mensaje, pero no puede usarse para encriptarlo. + +![La encriptación asimétrica utiliza una clave diferente para encriptar y desencriptar. La clave de encriptación se envía a los remitentes para que puedan encriptar un mensaje antes de enviarlo al receptor que posee las claves](../../../../../translated_images/send-message-asymmetric.7abe327c62615b8c19805252af5d4b6c5e7aaeb8fbc455efeff866fe2d300b62.es.png) + +El receptor comparte su clave pública, y el remitente la utiliza para encriptar el mensaje. Una vez enviado el mensaje, el receptor lo desencripta con su clave privada. La encriptación asimétrica es más segura porque la clave privada se mantiene privada por el receptor y nunca se comparte. Cualquiera puede tener la clave pública, ya que solo puede usarse para encriptar mensajes. + +La encriptación simétrica es más rápida que la asimétrica, pero la asimétrica es más segura. Algunos sistemas utilizan ambas: usan encriptación asimétrica para encriptar y compartir la clave simétrica, y luego usan la clave simétrica para encriptar todos los datos. Esto hace que sea más seguro compartir la clave simétrica entre el remitente y el receptor, y más rápido al encriptar y desencriptar datos. + +## Protege tus dispositivos IoT + +Los dispositivos IoT pueden protegerse utilizando encriptación simétrica o asimétrica. La simétrica es más sencilla, pero menos segura. + +### Claves simétricas + +Cuando configuraste tu dispositivo IoT para interactuar con IoT Hub, utilizaste una cadena de conexión. Un ejemplo de cadena de conexión es: + +```output +HostName=soil-moisture-sensor.azure-devices.net;DeviceId=soil-moisture-sensor;SharedAccessKey=Bhry+ind7kKEIDxubK61RiEHHRTrPl7HUow8cEm/mU0= +``` + +Esta cadena de conexión está compuesta por tres partes separadas por punto y coma, con cada parte siendo una clave y un valor: + +| Clave | Valor | Descripción | +| --- | ----- | ----------- | +| HostName | `soil-moisture-sensor.azure-devices.net` | La URL del IoT Hub | +| DeviceId | `soil-moisture-sensor` | El ID único del dispositivo | +| SharedAccessKey | `Bhry+ind7kKEIDxubK61RiEHHRTrPl7HUow8cEm/mU0=` | Una clave simétrica conocida por el dispositivo y el IoT Hub | + +La última parte de esta cadena de conexión, el `SharedAccessKey`, es la clave simétrica conocida tanto por el dispositivo como por el IoT Hub. Esta clave nunca se envía desde el dispositivo a la nube, ni de la nube al dispositivo. En su lugar, se utiliza para encriptar los datos que se envían o reciben. + +✅ Haz un experimento. ¿Qué crees que pasará si cambias la parte `SharedAccessKey` de la cadena de conexión al conectar tu dispositivo IoT? Pruébalo. + +Cuando el dispositivo intenta conectarse por primera vez, envía un token de firma de acceso compartido (SAS) que consiste en la URL del IoT Hub, una marca de tiempo que indica cuándo expirará la firma de acceso (generalmente 1 día desde el momento actual) y una firma. Esta firma consiste en la URL y el tiempo de expiración encriptados con la clave de acceso compartido de la cadena de conexión. + +El IoT Hub desencripta esta firma con la clave de acceso compartido, y si el valor desencriptado coincide con la URL y la expiración, se permite que el dispositivo se conecte. También verifica que la hora actual sea anterior a la expiración, para evitar que un dispositivo malicioso capture el token SAS de un dispositivo real y lo use. + +Esta es una forma elegante de verificar que el remitente es el dispositivo correcto. Al enviar algunos datos conocidos tanto en forma desencriptada como encriptada, el servidor puede verificar el dispositivo asegurándose de que, al desencriptar los datos encriptados, el resultado coincida con la versión desencriptada enviada. Si coincide, entonces tanto el remitente como el receptor tienen la misma clave de encriptación simétrica. +💁 Debido al tiempo de expiración, tu dispositivo IoT necesita conocer la hora exacta, que generalmente se obtiene de un servidor [NTP](https://wikipedia.org/wiki/Network_Time_Protocol). Si la hora no es precisa, la conexión fallará. +Después de la conexión, todos los datos enviados al IoT Hub desde el dispositivo, o al dispositivo desde el IoT Hub, estarán cifrados con la clave de acceso compartida. + +✅ ¿Qué crees que pasará si varios dispositivos comparten la misma cadena de conexión? + +> 💁 No es una buena práctica de seguridad almacenar esta clave en el código. Si un hacker obtiene tu código fuente, puede acceder a tu clave. Además, es más complicado al liberar el código, ya que necesitarías recompilar con una clave actualizada para cada dispositivo. Es mejor cargar esta clave desde un módulo de seguridad de hardware, un chip en el dispositivo IoT que almacena valores cifrados que tu código puede leer. +> +> Cuando estás aprendiendo sobre IoT, a menudo es más fácil poner la clave en el código, como hiciste en una lección anterior, pero debes asegurarte de que esta clave no se incluya en un control de código fuente público. + +Los dispositivos tienen 2 claves y 2 cadenas de conexión correspondientes. Esto permite rotar las claves, es decir, cambiar de una clave a otra si la primera se ve comprometida, y regenerar la primera clave. + +### Certificados X.509 + +Cuando utilizas cifrado asimétrico con un par de claves pública/privada, necesitas proporcionar tu clave pública a cualquiera que quiera enviarte datos. El problema es, ¿cómo puede el receptor de tu clave estar seguro de que realmente es tu clave pública y no alguien más haciéndose pasar por ti? En lugar de proporcionar una clave, puedes proporcionar tu clave pública dentro de un certificado que ha sido verificado por una tercera parte confiable, llamado certificado X.509. + +Los certificados X.509 son documentos digitales que contienen la parte pública del par de claves pública/privada. Generalmente son emitidos por una de varias organizaciones confiables llamadas [Autoridades de Certificación](https://wikipedia.org/wiki/Certificate_authority) (CAs) y están firmados digitalmente por la CA para indicar que la clave es válida y proviene de ti. Confías en el certificado y en que la clave pública es de quien el certificado dice que es, porque confías en la CA, de manera similar a cómo confiarías en un pasaporte o licencia de conducir porque confías en el país que lo emite. Los certificados tienen un costo, pero también puedes "autofirmarlos", es decir, crear un certificado tú mismo que esté firmado por ti, para fines de prueba. + +> 💁 Nunca deberías usar un certificado autofirmado para una versión de producción. + +Estos certificados tienen varios campos, incluyendo quién es el propietario de la clave pública, los detalles de la CA que lo emitió, cuánto tiempo es válido y la propia clave pública. Antes de usar un certificado, es una buena práctica verificarlo comprobando que fue firmado por la CA original. + +✅ Puedes leer una lista completa de los campos en el certificado en el [tutorial de Microsoft sobre certificados de clave pública X.509](https://docs.microsoft.com/azure/iot-hub/tutorial-x509-certificates?WT.mc_id=academic-17441-jabenn#certificate-fields). + +Cuando usas certificados X.509, tanto el remitente como el receptor tendrán sus propias claves públicas y privadas, así como certificados X.509 que contienen la clave pública. Luego intercambian los certificados X.509 de alguna manera, utilizando las claves públicas del otro para cifrar los datos que envían y sus propias claves privadas para descifrar los datos que reciben. + +![En lugar de compartir una clave pública, puedes compartir un certificado. El usuario del certificado puede verificar que proviene de ti comprobando con la autoridad de certificación que lo firmó.](../../../../../translated_images/send-message-certificate.9cc576ac1e46b76eb58ebc8eedaa522566fa0700076da46f5180aad78c2435db.es.png) + +Una gran ventaja de usar certificados X.509 es que pueden compartirse entre dispositivos. Puedes crear un certificado, subirlo al IoT Hub y usarlo para todos tus dispositivos. Cada dispositivo solo necesita conocer la clave privada para descifrar los mensajes que recibe del IoT Hub. + +El certificado usado por tu dispositivo para cifrar los mensajes que envía al IoT Hub es publicado por Microsoft. Es el mismo certificado que usan muchos servicios de Azure y, a veces, está integrado en los SDKs. + +> 💁 Recuerda, una clave pública es solo eso: pública. La clave pública de Azure solo puede usarse para cifrar datos enviados a Azure, no para descifrarlos, por lo que puede compartirse en cualquier lugar, incluso en el código fuente. Por ejemplo, puedes verla en el [código fuente del SDK de Azure IoT para C](https://github.com/Azure/azure-iot-sdk-c/blob/master/certs/certs.c). + +✅ Hay mucho vocabulario técnico relacionado con los certificados X.509. Puedes leer las definiciones de algunos de los términos que podrías encontrar en [La guía para principiantes sobre la jerga de los certificados X.509](https://techcommunity.microsoft.com/t5/internet-of-things/the-layman-s-guide-to-x-509-certificate-jargon/ba-p/2203540?WT.mc_id=academic-17441-jabenn). + +## Generar y usar un certificado X.509 + +Los pasos para generar un certificado X.509 son: + +1. Crear un par de claves pública/privada. Uno de los algoritmos más utilizados para generar un par de claves pública/privada se llama [Rivest–Shamir–Adleman](https://wikipedia.org/wiki/RSA_(cryptosystem)) (RSA). + +1. Enviar la clave pública con los datos asociados para su firma, ya sea por una CA o mediante autofirma. + +La CLI de Azure tiene comandos para crear una nueva identidad de dispositivo en IoT Hub, generar automáticamente el par de claves pública/privada y crear un certificado autofirmado. + +> 💁 Si quieres ver los pasos en detalle, en lugar de usar la CLI de Azure, puedes encontrarlos en el [tutorial sobre cómo usar OpenSSL para crear certificados autofirmados en la documentación de Microsoft IoT Hub](https://docs.microsoft.com/azure/iot-hub/tutorial-x509-self-sign?WT.mc_id=academic-17441-jabenn). + +### Tarea - crear una identidad de dispositivo usando un certificado X.509 + +1. Ejecuta el siguiente comando para registrar la nueva identidad de dispositivo, generando automáticamente las claves y certificados: + + ```sh + az iot hub device-identity create --device-id soil-moisture-sensor-x509 \ + --am x509_thumbprint \ + --output-dir . \ + --hub-name + ``` + + Sustituye `` por el nombre que usaste para tu IoT Hub. + + Esto creará un dispositivo con un ID de `soil-moisture-sensor-x509` para distinguirlo de la identidad de dispositivo que creaste en la lección anterior. Este comando también creará 2 archivos en el directorio actual: + + * `soil-moisture-sensor-x509-key.pem` - este archivo contiene la clave privada del dispositivo. + * `soil-moisture-sensor-x509-cert.pem` - este es el archivo de certificado X.509 del dispositivo. + + ¡Guarda estos archivos de forma segura! El archivo de clave privada no debe incluirse en un control de código fuente público. + +### Tarea - usar el certificado X.509 en el código de tu dispositivo + +Sigue la guía correspondiente para conectar tu dispositivo IoT a la nube usando el certificado X.509: + +* [Arduino - Wio Terminal](wio-terminal-x509.md) +* [Computadora de placa única - Raspberry Pi/Dispositivo IoT virtual](single-board-computer-x509.md) + +--- + +## 🚀 Desafío + +Existen múltiples formas de crear, gestionar y eliminar servicios de Azure como Grupos de Recursos e IoT Hubs. Una de ellas es el [Portal de Azure](https://portal.azure.com?WT.mc_id=academic-17441-jabenn), una interfaz web que te proporciona una GUI para gestionar tus servicios de Azure. + +Dirígete a [portal.azure.com](https://portal.azure.com?WT.mc_id=academic-17441-jabenn) e investiga el portal. Intenta crear un IoT Hub usando el portal y luego elimínalo. + +**Pista** - al crear servicios a través del portal, no necesitas crear un Grupo de Recursos por adelantado; puedes crear uno al mismo tiempo que el servicio. ¡Asegúrate de eliminarlo cuando termines! + +Puedes encontrar mucha documentación, tutoriales y guías sobre el Portal de Azure en la [documentación del portal de Azure](https://docs.microsoft.com/azure/azure-portal/?WT.mc_id=academic-17441-jabenn). + +## Cuestionario posterior a la lección + +[Cuestionario posterior a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/20) + +## Revisión y autoestudio + +* Lee sobre la historia de la criptografía en la [página de Historia de la criptografía en Wikipedia](https://wikipedia.org/wiki/History_of_cryptography). +* Lee sobre los certificados X.509 en la [página de X.509 en Wikipedia](https://wikipedia.org/wiki/X.509). + +## Asignación + +[Construye un nuevo dispositivo IoT](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/6-keep-your-plant-secure/assignment.md b/translations/es/2-farm/lessons/6-keep-your-plant-secure/assignment.md new file mode 100644 index 00000000..2eb403f0 --- /dev/null +++ b/translations/es/2-farm/lessons/6-keep-your-plant-secure/assignment.md @@ -0,0 +1,29 @@ + +# Construir un nuevo dispositivo IoT + +## Instrucciones + +En las últimas 6 lecciones, has aprendido sobre agricultura digital y cómo usar dispositivos IoT para recopilar datos, predecir el crecimiento de las plantas y automatizar el riego basado en lecturas de humedad del suelo. + +Usa lo que has aprendido para construir un nuevo dispositivo IoT utilizando un sensor y un actuador de tu elección. Envía telemetría a un IoT Hub y utiliza esa información para controlar un actuador mediante código sin servidor. Puedes usar un sensor y un actuador que ya hayas utilizado en este proyecto o en el anterior, o si tienes otro hardware, prueba algo nuevo. + +## Rúbrica + +| Criterio | Sobresaliente | Adecuado | Necesita Mejorar | +| -------- | ------------- | -------- | ---------------- | +| Programar un dispositivo IoT para usar un sensor y un actuador | Programó un dispositivo IoT que funciona con un sensor y un actuador | Programó un dispositivo IoT que funciona con un sensor o un actuador | No pudo programar un dispositivo IoT para usar un sensor o un actuador | +| Conectar el dispositivo IoT al IoT Hub | Fue capaz de implementar un IoT Hub, enviar telemetría y recibir comandos desde él | Fue capaz de implementar un IoT Hub y enviar telemetría o recibir comandos | No pudo implementar un IoT Hub ni comunicarse con él desde un dispositivo IoT | +| Controlar el actuador usando código sin servidor | Fue capaz de implementar una Azure Function para controlar el dispositivo activada por eventos de telemetría | Fue capaz de implementar una Azure Function activada por eventos de telemetría pero no pudo controlar el actuador | No pudo implementar una Azure Function | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/6-keep-your-plant-secure/single-board-computer-x509.md b/translations/es/2-farm/lessons/6-keep-your-plant-secure/single-board-computer-x509.md new file mode 100644 index 00000000..3669dd23 --- /dev/null +++ b/translations/es/2-farm/lessons/6-keep-your-plant-secure/single-board-computer-x509.md @@ -0,0 +1,71 @@ + +# Usa el certificado X.509 en el código de tu dispositivo - Hardware IoT Virtual y Raspberry Pi + +En esta parte de la lección, conectarás tu dispositivo IoT virtual o Raspberry Pi a tu IoT Hub utilizando el certificado X.509. + +## Conecta tu dispositivo al IoT Hub + +El siguiente paso es conectar tu dispositivo al IoT Hub utilizando los certificados X.509. + +### Tarea - conectar al IoT Hub + +1. Copia los archivos de clave y certificado a la carpeta que contiene el código de tu dispositivo IoT. Si estás utilizando una Raspberry Pi a través de VS Code Remote SSH y creaste las claves en tu PC o Mac, puedes arrastrar y soltar los archivos en el explorador de VS Code para copiarlos. + +1. Abre el archivo `app.py`. + +1. Para conectarte utilizando un certificado X.509, necesitarás el nombre del host del IoT Hub y el certificado X.509. Comienza creando una variable que contenga el nombre del host añadiendo el siguiente código antes de que se cree el cliente del dispositivo: + + ```python + host_name = "" + ``` + + Sustituye `` por el nombre del host de tu IoT Hub. Puedes obtenerlo de la sección `HostName` en el `connection_string`. Será el nombre de tu IoT Hub, terminando con `.azure-devices.net`. + +1. Debajo de esto, declara una variable con el ID del dispositivo: + + ```python + device_id = "soil-moisture-sensor-x509" + ``` + +1. Necesitarás una instancia de la clase `X509` que contenga los archivos X.509. Añade `X509` a la lista de clases importadas del módulo `azure.iot.device`: + + ```python + from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse, X509 + ``` + +1. Crea una instancia de la clase `X509` utilizando tus archivos de certificado y clave añadiendo este código debajo de la declaración de `host_name`: + + ```python + x509 = X509("./soil-moisture-sensor-x509-cert.pem", "./soil-moisture-sensor-x509-key.pem") + ``` + + Esto creará la clase `X509` utilizando los archivos `soil-moisture-sensor-x509-cert.pem` y `soil-moisture-sensor-x509-key.pem` creados anteriormente. + +1. Sustituye la línea de código que crea el `device_client` a partir de una cadena de conexión con lo siguiente: + + ```python + device_client = IoTHubDeviceClient.create_from_x509_certificate(x509, host_name, device_id) + ``` + + Esto conectará utilizando el certificado X.509 en lugar de una cadena de conexión. + +1. Elimina la línea con la variable `connection_string`. + +1. Ejecuta tu código. Monitorea los mensajes enviados al IoT Hub y envía solicitudes de métodos directos como antes. Verás que el dispositivo se conecta y envía lecturas de humedad del suelo, además de recibir solicitudes de métodos directos. + +> 💁 Puedes encontrar este código en la carpeta [code/pi](../../../../../2-farm/lessons/6-keep-your-plant-secure/code/pi) o [code/virtual-device](../../../../../2-farm/lessons/6-keep-your-plant-secure/code/virtual-device). + +😀 ¡Tu programa del sensor de humedad del suelo está conectado a tu IoT Hub utilizando un certificado X.509! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/2-farm/lessons/6-keep-your-plant-secure/wio-terminal-x509.md b/translations/es/2-farm/lessons/6-keep-your-plant-secure/wio-terminal-x509.md new file mode 100644 index 00000000..b29496c4 --- /dev/null +++ b/translations/es/2-farm/lessons/6-keep-your-plant-secure/wio-terminal-x509.md @@ -0,0 +1,17 @@ + +# Usar el certificado X.509 en el código de tu dispositivo - Wio Terminal + +En el momento de escribir esto, el SDK de Azure para Arduino no admite certificados X.509. Si deseas experimentar con certificados X.509, puedes consultar las [instrucciones para dispositivos IoT virtuales usando el SDK de Python](single-board-computer-x509.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/3-transport/README.md b/translations/es/3-transport/README.md new file mode 100644 index 00000000..3d4d1234 --- /dev/null +++ b/translations/es/3-transport/README.md @@ -0,0 +1,38 @@ + +# Transporte de la granja a la fábrica - usando IoT para rastrear entregas de alimentos + +Muchos agricultores cultivan alimentos para vender - ya sea que sean agricultores comerciales que venden todo lo que producen, o agricultores de subsistencia que venden su excedente para comprar lo necesario. De alguna manera, los alimentos tienen que llegar desde la granja al consumidor, y esto generalmente depende del transporte en grandes cantidades desde las granjas, a centros o plantas de procesamiento, y luego a las tiendas. Por ejemplo, un agricultor de tomates cosechará tomates, los empacará en cajas, cargará las cajas en un camión y los entregará a una planta de procesamiento. Los tomates serán clasificados y, desde allí, entregados a los consumidores en forma de alimentos procesados, ventas minoristas o consumidos en restaurantes. + +El IoT puede ayudar en esta cadena de suministro al rastrear los alimentos en tránsito - asegurándose de que los conductores vayan donde deben, monitoreando la ubicación de los vehículos y recibiendo alertas cuando los vehículos lleguen para que los alimentos puedan ser descargados y estén listos para ser procesados lo antes posible. + +> 🎓 Una *cadena de suministro* es la secuencia de actividades para fabricar y entregar algo. Por ejemplo, en el cultivo de tomates incluye la provisión de semillas, suelo, fertilizantes y agua, el cultivo de los tomates, la entrega de los tomates a un centro central, el transporte a un centro local de un supermercado, el transporte al supermercado individual, la exhibición en la tienda, la venta al consumidor y el traslado a casa para ser consumidos. Cada paso es como los eslabones de una cadena. + +> 🎓 La parte de transporte de la cadena de suministro se conoce como *logística*. + +En estas 4 lecciones, aprenderás cómo aplicar el Internet de las Cosas para mejorar la cadena de suministro al monitorear los alimentos mientras se cargan en un camión (virtual), que será rastreado mientras se dirige a su destino. Aprenderás sobre el rastreo GPS, cómo almacenar y visualizar datos de GPS, y cómo recibir alertas cuando un camión llegue a su destino. + +> 💁 Estas lecciones utilizarán algunos recursos en la nube. Si no completas todas las lecciones de este proyecto, asegúrate de [Limpiar tu proyecto](../clean-up.md). + +## Temas + +1. [Rastreo de ubicación](lessons/1-location-tracking/README.md) +1. [Almacenar datos de ubicación](lessons/2-store-location-data/README.md) +1. [Visualizar datos de ubicación](lessons/3-visualize-location-data/README.md) +1. [Geocercas](lessons/4-geofences/README.md) + +## Créditos + +Todas las lecciones fueron escritas con ♥️ por [Jen Looper](https://github.com/jlooper) y [Jim Bennett](https://GitHub.com/JimBobBennett) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/3-transport/lessons/1-location-tracking/README.md b/translations/es/3-transport/lessons/1-location-tracking/README.md new file mode 100644 index 00000000..bfe513f8 --- /dev/null +++ b/translations/es/3-transport/lessons/1-location-tracking/README.md @@ -0,0 +1,216 @@ + +# Seguimiento de ubicación + +![Una vista general ilustrada de esta lección](../../../../../translated_images/lesson-11.9fddbac4b664c6d50ab7ac9bb32f1fc3f945f03760e72f7f43938073762fb017.es.jpg) + +> Ilustración por [Nitya Narasimhan](https://github.com/nitya). Haz clic en la imagen para una versión más grande. + +## Cuestionario previo a la lección + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/21) + +## Introducción + +El proceso principal para llevar alimentos desde un agricultor hasta un consumidor implica cargar cajas de productos en camiones, barcos, aviones u otros vehículos de transporte comercial y entregar la comida en algún lugar, ya sea directamente a un cliente o a un centro o almacén para su procesamiento. Todo el proceso de principio a fin, desde la granja hasta el consumidor, forma parte de un proceso llamado *cadena de suministro*. El siguiente video de la Escuela de Negocios W. P. Carey de la Universidad Estatal de Arizona explica con más detalle el concepto de la cadena de suministro y cómo se gestiona. + +[![¿Qué es la gestión de la cadena de suministro? Un video de la Escuela de Negocios W. P. Carey de la Universidad Estatal de Arizona](https://img.youtube.com/vi/Mi1QBxVjZAw/0.jpg)](https://www.youtube.com/watch?v=Mi1QBxVjZAw) + +> 🎥 Haz clic en la imagen de arriba para ver el video + +Agregar dispositivos IoT puede mejorar drásticamente tu cadena de suministro, permitiéndote gestionar dónde están los artículos, planificar mejor el transporte y manejo de mercancías, y responder más rápido a los problemas. + +Cuando se gestiona una flota de vehículos como camiones, es útil saber dónde está cada vehículo en un momento dado. Los vehículos pueden equiparse con sensores GPS que envían su ubicación a sistemas IoT, permitiendo a los propietarios localizar su posición, ver la ruta que han tomado y saber cuándo llegarán a su destino. La mayoría de los vehículos operan fuera de la cobertura WiFi, por lo que utilizan redes celulares para enviar este tipo de datos. A veces, el sensor GPS está integrado en dispositivos IoT más complejos, como libros de registro electrónicos. Estos dispositivos rastrean cuánto tiempo ha estado un camión en tránsito para garantizar que los conductores cumplan con las leyes locales sobre horas de trabajo. + +En esta lección aprenderás cómo rastrear la ubicación de un vehículo utilizando un sensor del Sistema de Posicionamiento Global (GPS). + +En esta lección cubriremos: + +* [Vehículos conectados](../../../../../3-transport/lessons/1-location-tracking) +* [Coordenadas geoespaciales](../../../../../3-transport/lessons/1-location-tracking) +* [Sistemas de Posicionamiento Global (GPS)](../../../../../3-transport/lessons/1-location-tracking) +* [Leer datos de sensores GPS](../../../../../3-transport/lessons/1-location-tracking) +* [Datos GPS NMEA](../../../../../3-transport/lessons/1-location-tracking) +* [Decodificar datos de sensores GPS](../../../../../3-transport/lessons/1-location-tracking) + +## Vehículos conectados + +El IoT está transformando la forma en que se transportan los bienes al crear flotas de *vehículos conectados*. Estos vehículos están conectados a sistemas informáticos centrales que informan sobre su ubicación y otros datos de sensores. Tener una flota de vehículos conectados tiene una amplia gama de beneficios: + +* Seguimiento de ubicación: puedes localizar dónde está un vehículo en cualquier momento, lo que te permite: + + * Recibir alertas cuando un vehículo está a punto de llegar a un destino para preparar al equipo para la descarga. + * Localizar vehículos robados. + * Combinar datos de ubicación y ruta con problemas de tráfico para permitirte redirigir vehículos en medio del trayecto. + * Cumplir con impuestos. Algunos países cobran a los vehículos por la cantidad de kilómetros recorridos en carreteras públicas (como el [RUC de Nueva Zelanda](https://www.nzta.govt.nz/vehicles/licensing-rego/road-user-charges/)), por lo que saber cuándo un vehículo está en carreteras públicas frente a privadas facilita el cálculo de los impuestos adeudados. + * Saber dónde enviar equipos de mantenimiento en caso de avería. + +* Telemetría del conductor: poder garantizar que los conductores respeten los límites de velocidad, tomen curvas a velocidades adecuadas, frenen temprano y eficientemente, y conduzcan de manera segura. Los vehículos conectados también pueden tener cámaras para grabar incidentes. Esto puede estar vinculado al seguro, ofreciendo tarifas reducidas para buenos conductores. + +* Cumplimiento de horas de conducción: garantizar que los conductores solo conduzcan durante las horas legalmente permitidas según los momentos en que encienden y apagan el motor. + +Estos beneficios pueden combinarse, por ejemplo, combinando el cumplimiento de horas de conducción con el seguimiento de ubicación para redirigir a los conductores si no pueden llegar a su destino dentro de sus horas de conducción permitidas. También pueden combinarse con otra telemetría específica del vehículo, como datos de temperatura de camiones con control de temperatura, permitiendo redirigir vehículos si su ruta actual significaría que los bienes no pueden mantenerse a la temperatura adecuada. + +> 🎓 La logística es el proceso de transportar bienes de un lugar a otro, como de una granja a un supermercado a través de uno o más almacenes. Un agricultor empaca cajas de tomates que se cargan en un camión, se entregan en un almacén central y se colocan en un segundo camión que puede contener una mezcla de diferentes tipos de productos que luego se entregan en un supermercado. + +El componente principal del seguimiento de vehículos es el GPS: sensores que pueden localizar su posición en cualquier lugar de la Tierra. En esta lección aprenderás cómo usar un sensor GPS, comenzando por aprender cómo definir una ubicación en la Tierra. + +## Coordenadas geoespaciales + +Las coordenadas geoespaciales se utilizan para definir puntos en la superficie de la Tierra, similar a cómo las coordenadas pueden usarse para dibujar un píxel en una pantalla de computadora o posicionar puntos en un bordado. Para un solo punto, tienes un par de coordenadas. Por ejemplo, el campus de Microsoft en Redmond, Washington, EE. UU., está ubicado en 47.6423109, -122.1390293. + +### Latitud y longitud + +La Tierra es una esfera, un círculo tridimensional. Debido a esto, los puntos se definen dividiéndola en 360 grados, igual que la geometría de los círculos. La latitud mide el número de grados de norte a sur, y la longitud mide el número de grados de este a oeste. + +> 💁 Nadie sabe realmente la razón original por la cual los círculos se dividen en 360 grados. La [página de grados (ángulo) en Wikipedia](https://wikipedia.org/wiki/Degree_(angle)) cubre algunas de las posibles razones. + +![Líneas de latitud desde 90° en el Polo Norte, 45° a mitad de camino entre el Polo Norte y el ecuador, 0° en el ecuador, -45° a mitad de camino entre el ecuador y el Polo Sur, y -90° en el Polo Sur](../../../../../translated_images/latitude-lines.11d8d91dfb2014a57437272d7db7fd6607243098e8685f06e0c5f1ec984cb7eb.es.png) + +La latitud se mide utilizando líneas que rodean la Tierra y corren paralelas al ecuador, dividiendo los hemisferios norte y sur en 90° cada uno. El ecuador está en 0°, el Polo Norte está en 90°, también conocido como 90° Norte, y el Polo Sur está en -90°, o 90° Sur. + +La longitud se mide como el número de grados hacia el este y el oeste. El origen de 0° de longitud se llama el *Meridiano de Greenwich*, y fue definido en 1884 como una línea desde el Polo Norte al Polo Sur que pasa por el [Observatorio Real Británico en Greenwich, Inglaterra](https://wikipedia.org/wiki/Royal_Observatory,_Greenwich). + +![Líneas de longitud que van desde -180° al oeste del Meridiano de Greenwich, hasta 0° en el Meridiano de Greenwich, hasta 180° al este del Meridiano de Greenwich](../../../../../translated_images/longitude-meridians.ab4ef1c91c064586b0185a3c8d39e585903696c6a7d28c098a93a629cddb5d20.es.png) + +> 🎓 Un meridiano es una línea imaginaria recta que va desde el Polo Norte al Polo Sur, formando un semicírculo. + +Para medir la longitud de un punto, se mide el número de grados alrededor del ecuador desde el Meridiano de Greenwich hasta un meridiano que pasa por ese punto. La longitud va desde -180°, o 180° Oeste, pasando por 0° en el Meridiano de Greenwich, hasta 180°, o 180° Este. 180° y -180° se refieren al mismo punto, el antimeridiano o meridiano 180. Este es un meridiano en el lado opuesto de la Tierra al Meridiano de Greenwich. + +> 💁 El antimeridiano no debe confundirse con la Línea Internacional de Cambio de Fecha, que está aproximadamente en la misma posición, pero no es una línea recta y varía para ajustarse a las fronteras geopolíticas. + +✅ Investiga: Intenta encontrar la latitud y longitud de tu ubicación actual. + +### Grados, minutos y segundos vs grados decimales + +Tradicionalmente, las mediciones de grados de latitud y longitud se hacían utilizando numeración sexagesimal, o base-60, un sistema de numeración utilizado por los antiguos babilonios que realizaron las primeras mediciones y registros de tiempo y distancia. Probablemente usas el sistema sexagesimal todos los días sin darte cuenta, dividiendo horas en 60 minutos y minutos en 60 segundos. + +La longitud y la latitud se miden en grados, minutos y segundos, con un minuto siendo 1/60 de un grado, y 1 segundo siendo 1/60 de un minuto. + +Por ejemplo, en el ecuador: + +* 1° de latitud es **111.3 kilómetros** +* 1 minuto de latitud es 111.3/60 = **1.855 kilómetros** +* 1 segundo de latitud es 1.855/60 = **0.031 kilómetros** + +El símbolo para un minuto es una comilla simple, para un segundo es una comilla doble. Por ejemplo, 2 grados, 17 minutos y 43 segundos se escribiría como 2°17'43". Las partes de segundos se dan como decimales, por ejemplo, medio segundo es 0°0'0.5". + +Las computadoras no trabajan en base-60, por lo que estas coordenadas se dan como grados decimales al usar datos GPS en la mayoría de los sistemas informáticos. Por ejemplo, 2°17'43" es 2.295277. El símbolo de grado generalmente se omite. + +Las coordenadas de un punto siempre se dan como `latitud, longitud`, por lo que el ejemplo anterior del campus de Microsoft en 47.6423109,-122.117198 tiene: + +* Una latitud de 47.6423109 (47.6423109 grados al norte del ecuador) +* Una longitud de -122.1390293 (122.1390293 grados al oeste del Meridiano de Greenwich). + +![El campus de Microsoft en 47.6423109,-122.117198](../../../../../translated_images/microsoft-gps-location-world.a321d481b010f6adfcca139b2ba0adc53b79f58a540495b8e2ce7f779ea64bfe.es.png) + +## Sistemas de Posicionamiento Global (GPS) + +Los sistemas GPS utilizan múltiples satélites que orbitan la Tierra para localizar tu posición. Probablemente has usado sistemas GPS sin siquiera saberlo: para encontrar tu ubicación en una aplicación de mapas en tu teléfono como Apple Maps o Google Maps, para ver dónde está tu transporte en una aplicación de viajes como Uber o Lyft, o al usar navegación satelital (sat-nav) en tu automóvil. + +> 🎓 ¡Los satélites en la 'navegación satelital' son satélites GPS! + +Los sistemas GPS funcionan al tener varios satélites que envían una señal con la posición actual de cada satélite y una marca de tiempo precisa. Estas señales se envían a través de ondas de radio y son detectadas por una antena en el sensor GPS. Un sensor GPS detectará estas señales y, utilizando la hora actual, medirá cuánto tiempo tardó la señal en llegar al sensor desde el satélite. Debido a que la velocidad de las ondas de radio es constante, el sensor GPS puede usar la marca de tiempo enviada para calcular qué tan lejos está el sensor del satélite. Al combinar los datos de al menos 3 satélites con las posiciones enviadas, el sensor GPS puede determinar su ubicación en la Tierra. + +> 💁 Los sensores GPS necesitan antenas para detectar ondas de radio. Las antenas integradas en camiones y automóviles con GPS a bordo están posicionadas para obtener una buena señal, generalmente en el parabrisas o el techo. Si estás usando un sistema GPS separado, como un teléfono inteligente o un dispositivo IoT, entonces necesitas asegurarte de que la antena integrada en el sistema GPS o teléfono tenga una vista clara del cielo, como estar montada en tu parabrisas. + +![Al conocer la distancia del sensor a múltiples satélites, se puede calcular la ubicación](../../../../../translated_images/gps-satellites.04acf1148fe25fbf1586bc2e8ba698e8d79b79a50c36824b38417dd13372b90f.es.png) + +Los satélites GPS están orbitando la Tierra, no en un punto fijo sobre el sensor, por lo que los datos de ubicación incluyen la altitud sobre el nivel del mar además de la latitud y longitud. + +El GPS solía tener limitaciones de precisión impuestas por el ejército de EE. UU., limitando la precisión a aproximadamente 5 metros. Esta limitación se eliminó en el año 2000, permitiendo una precisión de 30 centímetros. Obtener esta precisión no siempre es posible debido a interferencias con las señales. + +✅ Si tienes un teléfono inteligente, abre la aplicación de mapas y observa qué tan precisa es tu ubicación. Puede tomar un breve período de tiempo para que tu teléfono detecte múltiples satélites y obtenga una ubicación más precisa. +💁 Los satélites contienen relojes atómicos que son increíblemente precisos, pero se desvían 38 microsegundos (0.0000038 segundos) al día en comparación con los relojes atómicos en la Tierra, debido a que el tiempo se ralentiza a medida que la velocidad aumenta, tal como lo predicen las teorías de la relatividad especial y general de Einstein. Los satélites viajan más rápido que la rotación de la Tierra. Este desvío se ha utilizado para confirmar las predicciones de la relatividad especial y general, y debe ajustarse en el diseño de los sistemas GPS. Literalmente, el tiempo transcurre más lento en un satélite GPS. +Los sistemas GPS han sido desarrollados y desplegados por varios países y uniones políticas, incluyendo EE. UU., Rusia, Japón, India, la UE y China. Los sensores GPS modernos pueden conectarse a la mayoría de estos sistemas para obtener ubicaciones más rápidas y precisas. + +> 🎓 Los grupos de satélites en cada despliegue se denominan constelaciones. + +## Leer datos del sensor GPS + +La mayoría de los sensores GPS envían datos GPS a través de UART. + +> ⚠️ UART se cubrió en [proyecto 2, lección 2](../../../2-farm/lessons/2-detect-soil-moisture/README.md#universal-asynchronous-receiver-transmitter-uart). Consulta esa lección si es necesario. + +Puedes usar un sensor GPS en tu dispositivo IoT para obtener datos GPS. + +### Tarea - conectar un sensor GPS y leer datos GPS + +Sigue la guía correspondiente para leer datos GPS usando tu dispositivo IoT: + +* [Arduino - Wio Terminal](wio-terminal-gps-sensor.md) +* [Computadora de placa única - Raspberry Pi](pi-gps-sensor.md) +* [Computadora de placa única - Dispositivo virtual](virtual-device-gps-sensor.md) + +## Datos GPS en formato NMEA + +Cuando ejecutaste tu código, probablemente viste lo que parecía ser un conjunto de caracteres sin sentido en la salida. En realidad, estos son datos GPS estándar, y todo tiene un significado. + +Los sensores GPS generan datos utilizando mensajes NMEA, siguiendo el estándar NMEA 0183. NMEA es un acrónimo de la [National Marine Electronics Association](https://www.nmea.org), una organización comercial con sede en EE. UU. que establece estándares para la comunicación entre dispositivos electrónicos marinos. + +> 💁 Este estándar es propietario y tiene un costo de al menos 2,000 USD, pero suficiente información sobre él está en el dominio público, lo que ha permitido que la mayor parte del estándar sea descifrada y utilizada en código abierto y otros proyectos no comerciales. + +Estos mensajes están basados en texto. Cada mensaje consiste en una *oración* que comienza con un carácter `$`, seguido de 2 caracteres que indican la fuente del mensaje (por ejemplo, GP para el sistema GPS de EE. UU., GN para GLONASS, el sistema GPS ruso) y 3 caracteres que indican el tipo de mensaje. El resto del mensaje son campos separados por comas, terminando con un carácter de nueva línea. + +Algunos de los tipos de mensajes que se pueden recibir son: + +| Tipo | Descripción | +| ---- | ----------- | +| GGA | Datos de fijación GPS, incluyendo la latitud, longitud y altitud del sensor GPS, junto con el número de satélites en vista para calcular esta fijación. | +| ZDA | La fecha y hora actuales, incluyendo la zona horaria local. | +| GSV | Detalles de los satélites en vista, definidos como los satélites de los que el sensor GPS puede detectar señales. | + +> 💁 Los datos GPS incluyen marcas de tiempo, por lo que tu dispositivo IoT puede obtener la hora si es necesario desde un sensor GPS, en lugar de depender de un servidor NTP o un reloj en tiempo real interno. + +El mensaje GGA incluye la ubicación actual usando el formato `(dd)dmm.mmmm`, junto con un carácter único para indicar la dirección. La `d` en el formato representa grados, la `m` representa minutos, y los segundos se expresan como decimales de minutos. Por ejemplo, 2°17'43" sería 217.716666667 - 2 grados, 17.716666667 minutos. + +El carácter de dirección puede ser `N` o `S` para latitud, indicando norte o sur, y `E` o `W` para longitud, indicando este u oeste. Por ejemplo, una latitud de 2°17'43" tendría un carácter de dirección `N`, mientras que -2°17'43" tendría un carácter de dirección `S`. + +Por ejemplo, la oración NMEA `$GNGGA,020604.001,4738.538654,N,12208.341758,W,1,3,,164.7,M,-17.1,M,,*67` + +* La parte de la latitud es `4738.538654,N`, que se convierte en 47.6423109 en grados decimales. `4738.538654` es 47.6423109, y la dirección es `N` (norte), por lo que es una latitud positiva. + +* La parte de la longitud es `12208.341758,W`, que se convierte en -122.1390293 en grados decimales. `12208.341758` es 122.1390293°, y la dirección es `W` (oeste), por lo que es una longitud negativa. + +## Decodificar datos del sensor GPS + +En lugar de usar los datos NMEA en bruto, es mejor decodificarlos en un formato más útil. Existen múltiples bibliotecas de código abierto que puedes usar para extraer datos útiles de los mensajes NMEA en bruto. + +### Tarea - decodificar datos del sensor GPS + +Sigue la guía correspondiente para decodificar datos del sensor GPS usando tu dispositivo IoT: + +* [Arduino - Wio Terminal](wio-terminal-gps-decode.md) +* [Computadora de placa única - Raspberry Pi/Dispositivo IoT virtual](single-board-computer-gps-decode.md) + +--- + +## 🚀 Desafío + +¡Escribe tu propio decodificador NMEA! En lugar de depender de bibliotecas de terceros para decodificar oraciones NMEA, ¿puedes escribir tu propio decodificador para extraer latitud y longitud de las oraciones NMEA? + +## Cuestionario posterior a la lección + +[Cuestionario posterior a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/22) + +## Revisión y autoestudio + +* Lee más sobre Coordenadas Geoespaciales en la [página del sistema de coordenadas geográficas en Wikipedia](https://wikipedia.org/wiki/Geographic_coordinate_system). +* Investiga sobre los Meridianos de Origen en otros cuerpos celestes además de la Tierra en la [página del Meridiano de Origen en Wikipedia](https://wikipedia.org/wiki/Prime_meridian#Prime_meridian_on_other_planetary_bodies). +* Investiga los diferentes sistemas GPS de varios gobiernos y uniones políticas como la UE, Japón, Rusia, India y EE. UU. + +## Asignación + +[Investiga otros datos GPS](assignment.md) + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/3-transport/lessons/1-location-tracking/assignment.md b/translations/es/3-transport/lessons/1-location-tracking/assignment.md new file mode 100644 index 00000000..a0df1d99 --- /dev/null +++ b/translations/es/3-transport/lessons/1-location-tracking/assignment.md @@ -0,0 +1,29 @@ + +# Investigar otros datos de GPS + +## Instrucciones + +Las oraciones NMEA que provienen de tu sensor GPS contienen otros datos además de la ubicación. Investiga los datos adicionales y utilízalos en tu dispositivo IoT. + +Por ejemplo, ¿puedes obtener la fecha y hora actuales? Si estás usando un microcontrolador, ¿puedes configurar el reloj utilizando los datos del GPS de la misma manera que lo hiciste con las señales NTP en el proyecto anterior? ¿Puedes obtener la altitud (tu altura sobre el nivel del mar) o tu velocidad actual? + +Si estás utilizando un dispositivo IoT virtual, puedes obtener algunos de estos datos enviando oraciones NMEA generadas con herramientas como [nmeagen.org](https://www.nmeagen.org). + +## Rúbrica + +| Criterios | Sobresaliente | Adecuado | Necesita Mejorar | +| --------- | ------------- | -------- | ----------------- | +| Obtener más datos de GPS | Es capaz de obtener y utilizar más datos de GPS, ya sea como telemetría o para configurar el dispositivo IoT | Es capaz de obtener más datos de GPS, pero no puede utilizarlos | No es capaz de obtener más datos de GPS | + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de ningún malentendido o interpretación errónea que surja del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/3-transport/lessons/1-location-tracking/pi-gps-sensor.md b/translations/es/3-transport/lessons/1-location-tracking/pi-gps-sensor.md new file mode 100644 index 00000000..d938637d --- /dev/null +++ b/translations/es/3-transport/lessons/1-location-tracking/pi-gps-sensor.md @@ -0,0 +1,193 @@ + +# Leer datos de GPS - Raspberry Pi + +En esta parte de la lección, agregarás un sensor GPS a tu Raspberry Pi y leerás valores de él. + +## Hardware + +La Raspberry Pi necesita un sensor GPS. + +El sensor que usarás es un [sensor Grove GPS Air530](https://www.seeedstudio.com/Grove-GPS-Air530-p-4584.html). Este sensor puede conectarse a múltiples sistemas GPS para obtener una ubicación rápida y precisa. El sensor está compuesto por 2 partes: la electrónica principal del sensor y una antena externa conectada por un cable delgado para captar las ondas de radio de los satélites. + +Este es un sensor UART, por lo que envía datos GPS a través de UART. + +## Conectar el sensor GPS + +El sensor Grove GPS puede conectarse a la Raspberry Pi. + +### Tarea - conectar el sensor GPS + +Conecta el sensor GPS. + +![Un sensor Grove GPS](../../../../../translated_images/grove-gps-sensor.247943bf69b03f0d1820ef6ed10c587f9b650e8db55b936851c92412180bd3e2.es.png) + +1. Inserta un extremo de un cable Grove en el conector del sensor GPS. Solo encajará de una manera. + +1. Con la Raspberry Pi apagada, conecta el otro extremo del cable Grove al conector UART marcado como **UART** en el Grove Base Hat conectado a la Pi. Este conector está en la fila del medio, en el lado más cercano a la ranura de la tarjeta SD, en el extremo opuesto a los puertos USB y el conector Ethernet. + + ![El sensor Grove GPS conectado al conector UART](../../../../../translated_images/pi-gps-sensor.1f99ee2b2f6528915047ec78967bd362e0e4ee0ed594368a3837b9cf9cdaca64.es.png) + +1. Coloca el sensor GPS de manera que la antena conectada tenga visibilidad al cielo, idealmente cerca de una ventana abierta o al aire libre. Es más fácil obtener una señal clara sin obstáculos para la antena. + +## Programar el sensor GPS + +La Raspberry Pi ahora puede ser programada para usar el sensor GPS conectado. + +### Tarea - programar el sensor GPS + +Programa el dispositivo. + +1. Enciende la Pi y espera a que arranque. + +1. El sensor GPS tiene 2 LEDs: un LED azul que parpadea cuando se transmiten datos y un LED verde que parpadea cada segundo cuando recibe datos de los satélites. Asegúrate de que el LED azul esté parpadeando cuando enciendas la Pi. Después de unos minutos, el LED verde comenzará a parpadear; si no lo hace, puede que necesites reposicionar la antena. + +1. Abre VS Code, ya sea directamente en la Pi o conectándote mediante la extensión Remote SSH. + + > ⚠️ Puedes consultar [las instrucciones para configurar y abrir VS Code en la lección 1 si lo necesitas](../../../1-getting-started/lessons/1-introduction-to-iot/pi.md). + +1. Con las versiones más recientes de la Raspberry Pi que admiten Bluetooth, existe un conflicto entre el puerto serial utilizado para Bluetooth y el utilizado por el puerto UART del Grove. Para solucionarlo, haz lo siguiente: + + 1. Desde el terminal de VS Code, edita el archivo `/boot/config.txt` usando `nano`, un editor de texto integrado en el terminal, con el siguiente comando: + + ```sh + sudo nano /boot/config.txt + ``` + + > Este archivo no puede ser editado por VS Code ya que necesitas permisos elevados (`sudo`). VS Code no ejecuta esta función. + + 1. Usa las teclas de dirección para navegar al final del archivo, luego copia el código a continuación y pégalo al final del archivo: + + ```ini + dtoverlay=pi3-miniuart-bt + dtoverlay=pi3-disable-bt + enable_uart=1 + ``` + + Puedes pegar usando los atajos de teclado normales de tu dispositivo (`Ctrl+v` en Windows, Linux o Raspberry Pi OS, `Cmd+v` en macOS). + + 1. Guarda este archivo y sal de nano presionando `Ctrl+x`. Presiona `y` cuando se te pregunte si deseas guardar el buffer modificado, luego presiona `enter` para confirmar que deseas sobrescribir `/boot/config.txt`. + + > Si cometes un error, puedes salir sin guardar y repetir estos pasos. + + 1. Edita el archivo `/boot/cmdline.txt` en nano con el siguiente comando: + + ```sh + sudo nano /boot/cmdline.txt + ``` + + 1. Este archivo tiene varios pares clave/valor separados por espacios. Elimina cualquier par clave/valor para la clave `console`. Probablemente se verán algo así: + + ```output + console=serial0,115200 console=tty1 + ``` + + Puedes navegar a estas entradas usando las teclas de dirección y luego eliminarlas usando las teclas `del` o `backspace`. + + Por ejemplo, si tu archivo original se ve así: + + ```output + console=serial0,115200 console=tty1 root=PARTUUID=058e2867-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait + ``` + + La nueva versión será: + + ```output + root=PARTUUID=058e2867-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait + ``` + + 1. Sigue los pasos anteriores para guardar este archivo y salir de nano. + + 1. Reinicia tu Pi y luego vuelve a conectarte en VS Code una vez que la Pi haya reiniciado. + +1. Desde el terminal, crea una nueva carpeta en el directorio de inicio del usuario `pi` llamada `gps-sensor`. Crea un archivo en esta carpeta llamado `app.py`. + +1. Abre esta carpeta en VS Code. + +1. El módulo GPS envía datos UART a través de un puerto serial. Instala el paquete Pip `pyserial` para comunicarte con el puerto serial desde tu código Python: + + ```sh + pip3 install pyserial + ``` + +1. Agrega el siguiente código a tu archivo `app.py`: + + ```python + import time + import serial + + serial = serial.Serial('/dev/ttyAMA0', 9600, timeout=1) + serial.reset_input_buffer() + serial.flush() + + def print_gps_data(line): + print(line.rstrip()) + + while True: + line = serial.readline().decode('utf-8') + + while len(line) > 0: + print_gps_data(line) + line = serial.readline().decode('utf-8') + + time.sleep(1) + ``` + + Este código importa el módulo `serial` del paquete Pip `pyserial`. Luego se conecta al puerto serial `/dev/ttyAMA0`, que es la dirección del puerto serial que utiliza el Grove Pi Base Hat para su puerto UART. Después, limpia cualquier dato existente de esta conexión serial. + + A continuación, se define una función llamada `print_gps_data` que imprime en la consola la línea que se le pasa. + + Luego, el código entra en un bucle infinito, leyendo tantas líneas de texto como pueda del puerto serial en cada iteración. Llama a la función `print_gps_data` para cada línea. + + Después de leer todos los datos, el bucle duerme durante 1 segundo y luego intenta nuevamente. + +1. Ejecuta este código. Verás la salida en bruto del sensor GPS, algo como lo siguiente: + + ```output + $GNGGA,020604.001,4738.538654,N,12208.341758,W,1,3,,164.7,M,-17.1,M,,*67 + $GPGSA,A,1,,,,,,,,,,,,,,,*1E + $BDGSA,A,1,,,,,,,,,,,,,,,*0F + $GPGSV,1,1,00*79 + $BDGSV,1,1,00*68 + ``` + + > Si obtienes uno de los siguientes errores al detener y reiniciar tu código, agrega un bloque `try - except` a tu bucle while. + + ```output + UnicodeDecodeError: 'utf-8' codec can't decode byte 0x93 in position 0: invalid start byte + UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 0: invalid continuation byte + ``` + + ```python + while True: + try: + line = serial.readline().decode('utf-8') + + while len(line) > 0: + print_gps_data() + line = serial.readline().decode('utf-8') + + # There's a random chance the first byte being read is part way through a character. + # Read another full line and continue. + + except UnicodeDecodeError: + line = serial.readline().decode('utf-8') + + time.sleep(1) + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-gps/pi](../../../../../3-transport/lessons/1-location-tracking/code-gps/pi). + +😀 ¡Tu programa del sensor GPS fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/3-transport/lessons/1-location-tracking/single-board-computer-gps-decode.md b/translations/es/3-transport/lessons/1-location-tracking/single-board-computer-gps-decode.md new file mode 100644 index 00000000..d7166688 --- /dev/null +++ b/translations/es/3-transport/lessons/1-location-tracking/single-board-computer-gps-decode.md @@ -0,0 +1,75 @@ + +# Decodificar datos GPS - Hardware IoT Virtual y Raspberry Pi + +En esta parte de la lección, decodificarás los mensajes NMEA leídos del sensor GPS por la Raspberry Pi o el Dispositivo IoT Virtual, y extraerás la latitud y la longitud. + +## Decodificar datos GPS + +Una vez que los datos NMEA en bruto se han leído desde el puerto serial, pueden ser decodificados utilizando una biblioteca NMEA de código abierto. + +### Tarea - decodificar datos GPS + +Programa el dispositivo para decodificar los datos GPS. + +1. Abre el proyecto de la aplicación `gps-sensor` si aún no está abierto. + +1. Instala el paquete Pip `pynmea2`. Este paquete contiene código para decodificar mensajes NMEA. + + ```sh + pip3 install pynmea2 + ``` + +1. Agrega el siguiente código a las importaciones en el archivo `app.py` para importar el módulo `pynmea2`: + + ```python + import pynmea2 + ``` + +1. Reemplaza el contenido de la función `print_gps_data` con lo siguiente: + + ```python + msg = pynmea2.parse(line) + if msg.sentence_type == 'GGA': + lat = pynmea2.dm_to_sd(msg.lat) + lon = pynmea2.dm_to_sd(msg.lon) + + if msg.lat_dir == 'S': + lat = lat * -1 + + if msg.lon_dir == 'W': + lon = lon * -1 + + print(f'{lat},{lon} - from {msg.num_sats} satellites') + ``` + + Este código utilizará la biblioteca `pynmea2` para analizar la línea leída desde el puerto serial UART. + + Si el tipo de sentencia del mensaje es `GGA`, entonces este es un mensaje de fijación de posición y se procesa. Los valores de latitud y longitud se leen del mensaje y se convierten a grados decimales desde el formato NMEA `(d)ddmm.mmmm`. La función `dm_to_sd` realiza esta conversión. + + Luego se verifica la dirección de la latitud, y si la latitud es sur, el valor se convierte en un número negativo. Lo mismo ocurre con la longitud; si es oeste, se convierte en un número negativo. + + Finalmente, las coordenadas se imprimen en la consola, junto con el número de satélites utilizados para obtener la ubicación. + +1. Ejecuta el código. Si estás utilizando un dispositivo IoT virtual, asegúrate de que la aplicación CounterFit esté ejecutándose y que los datos GPS se estén enviando. + + ```output + pi@raspberrypi:~/gps-sensor $ python3 app.py + 47.6423109,-122.1390293 - from 3 satellites + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-gps-decode/virtual-device](../../../../../3-transport/lessons/1-location-tracking/code-gps-decode/virtual-device), o en la carpeta [code-gps-decode/pi](../../../../../3-transport/lessons/1-location-tracking/code-gps-decode/pi). + +😀 ¡Tu programa del sensor GPS con decodificación de datos fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/3-transport/lessons/1-location-tracking/virtual-device-gps-sensor.md b/translations/es/3-transport/lessons/1-location-tracking/virtual-device-gps-sensor.md new file mode 100644 index 00000000..d1f5bdd0 --- /dev/null +++ b/translations/es/3-transport/lessons/1-location-tracking/virtual-device-gps-sensor.md @@ -0,0 +1,144 @@ + +# Leer datos GPS - Hardware IoT Virtual + +En esta parte de la lección, agregarás un sensor GPS a tu dispositivo IoT virtual y leerás valores de él. + +## Hardware Virtual + +El dispositivo IoT virtual usará un sensor GPS simulado que es accesible a través de UART mediante un puerto serial. + +Un sensor GPS físico tendrá una antena para captar ondas de radio de los satélites GPS y convertir las señales GPS en datos GPS. La versión virtual simula esto permitiéndote establecer una latitud y longitud, enviar sentencias NMEA en bruto o cargar un archivo GPX con múltiples ubicaciones que se pueden devolver secuencialmente. + +> 🎓 Las sentencias NMEA se cubrirán más adelante en esta lección. + +### Agregar el sensor a CounterFit + +Para usar un sensor GPS virtual, necesitas agregar uno a la aplicación CounterFit. + +#### Tarea - agregar el sensor a CounterFit + +Agrega el sensor GPS a la aplicación CounterFit. + +1. Crea una nueva aplicación en Python en tu computadora dentro de una carpeta llamada `gps-sensor` con un único archivo llamado `app.py` y un entorno virtual de Python, y agrega los paquetes pip de CounterFit. + + > ⚠️ Puedes consultar [las instrucciones para crear y configurar un proyecto Python de CounterFit en la lección 1 si lo necesitas](../../../1-getting-started/lessons/1-introduction-to-iot/virtual-device.md). + +1. Instala un paquete adicional de Pip para instalar un shim de CounterFit que pueda comunicarse con sensores basados en UART a través de una conexión serial. Asegúrate de instalarlo desde un terminal con el entorno virtual activado. + + ```sh + pip install counterfit-shims-serial + ``` + +1. Asegúrate de que la aplicación web de CounterFit esté en ejecución. + +1. Crea un sensor GPS: + + 1. En el cuadro *Create sensor* en el panel *Sensors*, despliega el cuadro *Sensor type* y selecciona *UART GPS*. + + 1. Deja el *Port* configurado como */dev/ttyAMA0*. + + 1. Selecciona el botón **Add** para crear el sensor GPS en el puerto `/dev/ttyAMA0`. + + ![Configuración del sensor GPS](../../../../../translated_images/counterfit-create-gps-sensor.6385dc9357d85ad1d47b4abb2525e7651fd498917d25eefc5a72feab09eedc70.es.png) + + El sensor GPS será creado y aparecerá en la lista de sensores. + + ![Sensor GPS creado](../../../../../translated_images/counterfit-gps-sensor.3fbb15af0a5367566f2f11324ef5a6f30861cdf2b497071a5e002b7aa473550e.es.png) + +## Programar el sensor GPS + +El dispositivo IoT virtual ahora puede ser programado para usar el sensor GPS virtual. + +### Tarea - programar el sensor GPS + +Programa la aplicación del sensor GPS. + +1. Asegúrate de que la aplicación `gps-sensor` esté abierta en VS Code. + +1. Abre el archivo `app.py`. + +1. Agrega el siguiente código al inicio de `app.py` para conectar la aplicación a CounterFit: + + ```python + from counterfit_connection import CounterFitConnection + CounterFitConnection.init('127.0.0.1', 5000) + ``` + +1. Agrega el siguiente código debajo de este para importar algunas bibliotecas necesarias, incluida la biblioteca para el puerto serial de CounterFit: + + ```python + import time + import counterfit_shims_serial + + serial = counterfit_shims_serial.Serial('/dev/ttyAMA0') + ``` + + Este código importa el módulo `serial` del paquete Pip `counterfit_shims_serial`. Luego se conecta al puerto serial `/dev/ttyAMA0`, que es la dirección del puerto serial que el sensor GPS virtual utiliza para su puerto UART. + +1. Agrega el siguiente código debajo de este para leer desde el puerto serial e imprimir los valores en la consola: + + ```python + def print_gps_data(line): + print(line.rstrip()) + + while True: + line = serial.readline().decode('utf-8') + + while len(line) > 0: + print_gps_data(line) + line = serial.readline().decode('utf-8') + + time.sleep(1) + ``` + + Se define una función llamada `print_gps_data` que imprime en la consola la línea que se le pasa. + + Luego, el código entra en un bucle infinito, leyendo tantas líneas de texto como pueda desde el puerto serial en cada iteración. Llama a la función `print_gps_data` para cada línea. + + Después de leer todos los datos, el bucle duerme durante 1 segundo y luego lo intenta de nuevo. + +1. Ejecuta este código, asegurándote de usar un terminal diferente al que está ejecutando la aplicación CounterFit, para que la aplicación CounterFit siga funcionando. + +1. Desde la aplicación CounterFit, cambia el valor del sensor GPS. Puedes hacerlo de una de estas maneras: + + * Configura la **Source** como `Lat/Lon` y establece una latitud, longitud y número de satélites utilizados para obtener la posición GPS. Este valor se enviará solo una vez, así que marca la casilla **Repeat** para que los datos se repitan cada segundo. + + ![El sensor GPS con lat lon seleccionado](../../../../../translated_images/counterfit-gps-sensor-latlon.008c867d75464fbe7f84107cc57040df565ac07cb57d2f21db37d087d470197d.es.png) + + * Configura la **Source** como `NMEA` y agrega algunas sentencias NMEA en el cuadro de texto. Todos estos valores se enviarán, con un retraso de 1 segundo antes de que se pueda leer cada nueva sentencia GGA (posición fija). + + ![El sensor GPS con sentencias NMEA configuradas](../../../../../translated_images/counterfit-gps-sensor-nmea.c62eea442171e17e19528b051b104cfcecdc9cd18db7bc72920f29821ae63f73.es.png) + + Puedes usar una herramienta como [nmeagen.org](https://www.nmeagen.org) para generar estas sentencias dibujando en un mapa. Estos valores se enviarán solo una vez, así que marca la casilla **Repeat** para que los datos se repitan un segundo después de que se hayan enviado todos. + + * Configura la **Source** como archivo GPX y carga un archivo GPX con ubicaciones de ruta. Puedes descargar archivos GPX de varios sitios populares de mapas y senderismo, como [AllTrails](https://www.alltrails.com/). Estos archivos contienen múltiples ubicaciones GPS como un recorrido, y el sensor GPS devolverá cada nueva ubicación en intervalos de 1 segundo. + + ![El sensor GPS con un archivo GPX configurado](../../../../../translated_images/counterfit-gps-sensor-gpxfile.8310b063ce8a425ccc8ebeec8306aeac5e8e55207f007d52c6e1194432a70cd9.es.png) + + Estos valores se enviarán solo una vez, así que marca la casilla **Repeat** para que los datos se repitan un segundo después de que se hayan enviado todos. + + Una vez que hayas configurado los ajustes del GPS, selecciona el botón **Set** para confirmar estos valores en el sensor. + +1. Verás la salida en bruto del sensor GPS, algo como lo siguiente: + + ```output + $GNGGA,020604.001,4738.538654,N,12208.341758,W,1,3,,164.7,M,-17.1,M,,*67 + $GNGGA,020604.001,4738.538654,N,12208.341758,W,1,3,,164.7,M,-17.1,M,,*67 + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-gps/virtual-device](../../../../../3-transport/lessons/1-location-tracking/code-gps/virtual-device). + +😀 ¡Tu programa del sensor GPS fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/3-transport/lessons/1-location-tracking/wio-terminal-gps-decode.md b/translations/es/3-transport/lessons/1-location-tracking/wio-terminal-gps-decode.md new file mode 100644 index 00000000..e5a4ddc6 --- /dev/null +++ b/translations/es/3-transport/lessons/1-location-tracking/wio-terminal-gps-decode.md @@ -0,0 +1,83 @@ + +# Decodificar datos GPS - Wio Terminal + +En esta parte de la lección, decodificarás los mensajes NMEA leídos desde el sensor GPS por el Wio Terminal y extraerás la latitud y la longitud. + +## Decodificar datos GPS + +Una vez que se hayan leído los datos NMEA en bruto desde el puerto serie, se pueden decodificar utilizando una biblioteca NMEA de código abierto. + +### Tarea - decodificar datos GPS + +Programa el dispositivo para decodificar los datos GPS. + +1. Abre el proyecto de la aplicación `gps-sensor` si aún no está abierto. + +1. Agrega una dependencia de biblioteca para la biblioteca [TinyGPSPlus](https://github.com/mikalhart/TinyGPSPlus) en el archivo `platformio.ini` del proyecto. Esta biblioteca contiene el código necesario para decodificar datos NMEA. + + ```ini + lib_deps = + mikalhart/TinyGPSPlus @ 1.0.2 + ``` + +1. En `main.cpp`, agrega una directiva de inclusión para la biblioteca TinyGPSPlus: + + ```cpp + #include + ``` + +1. Debajo de la declaración de `Serial3`, declara un objeto TinyGPSPlus para procesar las sentencias NMEA: + + ```cpp + TinyGPSPlus gps; + ``` + +1. Cambia el contenido de la función `printGPSData` al siguiente: + + ```cpp + if (gps.encode(Serial3.read())) + { + if (gps.location.isValid()) + { + Serial.print(gps.location.lat(), 6); + Serial.print(F(",")); + Serial.print(gps.location.lng(), 6); + Serial.print(" - from "); + Serial.print(gps.satellites.value()); + Serial.println(" satellites"); + } + } + ``` + + Este código lee el siguiente carácter desde el puerto serie UART en el decodificador NMEA `gps`. Después de cada carácter, verificará si el decodificador ha leído una sentencia válida y luego comprobará si ha leído una ubicación válida. Si la ubicación es válida, la enviará al monitor serie junto con el número de satélites que contribuyeron a esta solución. + +1. Compila y sube el código al Wio Terminal. + +1. Una vez subido, puedes monitorear los datos de ubicación GPS utilizando el monitor serie. + + ```output + > Executing task: platformio device monitor < + + --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time + --- More details at http://bit.ly/pio-monitor-filters + --- Miniterm on /dev/cu.usbmodem1201 9600,8,N,1 --- + --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + 47.6423109,-122.1390293 - from 3 satellites + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-gps-decode/wio-terminal](../../../../../3-transport/lessons/1-location-tracking/code-gps-decode/wio-terminal). + +😀 ¡Tu programa del sensor GPS con decodificación de datos fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/3-transport/lessons/1-location-tracking/wio-terminal-gps-sensor.md b/translations/es/3-transport/lessons/1-location-tracking/wio-terminal-gps-sensor.md new file mode 100644 index 00000000..bccfb01c --- /dev/null +++ b/translations/es/3-transport/lessons/1-location-tracking/wio-terminal-gps-sensor.md @@ -0,0 +1,154 @@ + +# Leer datos GPS - Wio Terminal + +En esta parte de la lección, agregarás un sensor GPS a tu Wio Terminal y leerás valores de él. + +## Hardware + +El Wio Terminal necesita un sensor GPS. + +El sensor que usarás es un [sensor Grove GPS Air530](https://www.seeedstudio.com/Grove-GPS-Air530-p-4584.html). Este sensor puede conectarse a múltiples sistemas GPS para obtener una ubicación rápida y precisa. El sensor está compuesto por 2 partes: la electrónica principal del sensor y una antena externa conectada por un cable delgado para captar las ondas de radio de los satélites. + +Este es un sensor UART, por lo que envía datos GPS a través de UART. + +### Conectar el sensor GPS + +El sensor Grove GPS se puede conectar al Wio Terminal. + +#### Tarea - conectar el sensor GPS + +Conecta el sensor GPS. + +![Un sensor Grove GPS](../../../../../translated_images/grove-gps-sensor.247943bf69b03f0d1820ef6ed10c587f9b650e8db55b936851c92412180bd3e2.es.png) + +1. Inserta un extremo de un cable Grove en el conector del sensor GPS. Solo encajará de una manera. + +1. Con el Wio Terminal desconectado de tu computadora u otra fuente de alimentación, conecta el otro extremo del cable Grove al conector Grove del lado izquierdo del Wio Terminal, mirando la pantalla. Este es el conector más cercano al botón de encendido. + + ![El sensor Grove GPS conectado al conector izquierdo](../../../../../translated_images/wio-gps-sensor.19fd52b81ce58095d5deb3d4e5a1fdd88818d76569b00b1f0d740c92dc986525.es.png) + +1. Coloca el sensor GPS de manera que la antena conectada tenga visibilidad al cielo, idealmente cerca de una ventana abierta o al aire libre. Es más fácil obtener una señal clara sin obstáculos frente a la antena. + +1. Ahora puedes conectar el Wio Terminal a tu computadora. + +1. El sensor GPS tiene 2 LEDs: un LED azul que parpadea cuando se transmiten datos y un LED verde que parpadea cada segundo al recibir datos de los satélites. Asegúrate de que el LED azul parpadee cuando enciendas el Wio Terminal. Después de unos minutos, el LED verde debería parpadear; si no, es posible que necesites reposicionar la antena. + +## Programar el sensor GPS + +Ahora se puede programar el Wio Terminal para usar el sensor GPS conectado. + +### Tarea - programar el sensor GPS + +Programa el dispositivo. + +1. Crea un nuevo proyecto para el Wio Terminal usando PlatformIO. Llama a este proyecto `gps-sensor`. Agrega código en la función `setup` para configurar el puerto serial. + +1. Agrega la siguiente directiva `include` en la parte superior del archivo `main.cpp`. Esto incluye un archivo de cabecera con funciones para configurar el puerto Grove izquierdo para UART. + + ```cpp + #include + ``` + +1. Debajo de esto, agrega la siguiente línea de código para declarar una conexión de puerto serial al puerto UART: + + ```cpp + static Uart Serial3(&sercom3, PIN_WIRE_SCL, PIN_WIRE_SDA, SERCOM_RX_PAD_1, UART_TX_PAD_0); + ``` + +1. Necesitas agregar algo de código para redirigir algunos manejadores de señales internas a este puerto serial. Agrega el siguiente código debajo de la declaración de `Serial3`: + + ```cpp + void SERCOM3_0_Handler() + { + Serial3.IrqHandler(); + } + + void SERCOM3_1_Handler() + { + Serial3.IrqHandler(); + } + + void SERCOM3_2_Handler() + { + Serial3.IrqHandler(); + } + + void SERCOM3_3_Handler() + { + Serial3.IrqHandler(); + } + ``` + +1. En la función `setup`, debajo de donde se configura el puerto `Serial`, configura el puerto serial UART con el siguiente código: + + ```cpp + Serial3.begin(9600); + + while (!Serial3) + ; // Wait for Serial3 to be ready + + delay(1000); + ``` + +1. Debajo de este código en la función `setup`, agrega el siguiente código para conectar el pin Grove al puerto serial: + + ```cpp + pinPeripheral(PIN_WIRE_SCL, PIO_SERCOM_ALT); + ``` + +1. Agrega la siguiente función antes de la función `loop` para enviar los datos GPS al monitor serial: + + ```cpp + void printGPSData() + { + Serial.println(Serial3.readStringUntil('\n')); + } + ``` + +1. En la función `loop`, agrega el siguiente código para leer del puerto serial UART e imprimir la salida en el monitor serial: + + ```cpp + while (Serial3.available() > 0) + { + printGPSData(); + } + + delay(1000); + ``` + + Este código lee del puerto serial UART. La función `readStringUntil` lee hasta un carácter terminador, en este caso, una nueva línea. Esto leerá una oración completa en formato NMEA (las oraciones NMEA terminan con un carácter de nueva línea). Mientras se puedan leer datos del puerto serial UART, se leen y se envían al monitor serial a través de la función `printGPSData`. Una vez que no se puedan leer más datos, el `loop` se retrasa por 1 segundo (1,000 ms). + +1. Compila y sube el código al Wio Terminal. + +1. Una vez subido, puedes monitorear los datos GPS usando el monitor serial. + + ```output + > Executing task: platformio device monitor < + + --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time + --- More details at http://bit.ly/pio-monitor-filters + --- Miniterm on /dev/cu.usbmodem1201 9600,8,N,1 --- + --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + $GNGGA,020604.001,4738.538654,N,12208.341758,W,1,3,,164.7,M,-17.1,M,,*67 + $GPGSA,A,1,,,,,,,,,,,,,,,*1E + $BDGSA,A,1,,,,,,,,,,,,,,,*0F + $GPGSV,1,1,00*79 + $BDGSV,1,1,00*68 + ``` + +> 💁 Puedes encontrar este código en la carpeta [code-gps/wio-terminal](../../../../../3-transport/lessons/1-location-tracking/code-gps/wio-terminal). + +😀 ¡Tu programa del sensor GPS fue un éxito! + +--- + +**Descargo de responsabilidad**: +Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción. \ No newline at end of file diff --git a/translations/es/3-transport/lessons/2-store-location-data/README.md b/translations/es/3-transport/lessons/2-store-location-data/README.md new file mode 100644 index 00000000..e7234c61 --- /dev/null +++ b/translations/es/3-transport/lessons/2-store-location-data/README.md @@ -0,0 +1,479 @@ + +# Datos de ubicación de la tienda + +![Una vista general en sketchnote de esta lección](../../../../../translated_images/lesson-12.ca7f53039712a3ec14ad6474d8445361c84adab643edc53fa6269b77895606bb.es.jpg) + +> Sketchnote por [Nitya Narasimhan](https://github.com/nitya). Haz clic en la imagen para una versión más grande. + +## Cuestionario previo a la lección + +[Cuestionario previo a la lección](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/23) + +## Introducción + +En la última lección, aprendiste cómo usar un sensor GPS para capturar datos de ubicación. Para usar estos datos y visualizar la ubicación de un camión cargado de alimentos y su recorrido, es necesario enviarlos a un servicio IoT en la nube y luego almacenarlos en algún lugar. + +En esta lección aprenderás sobre las diferentes formas de almacenar datos IoT y cómo guardar datos de tu servicio IoT utilizando código sin servidor. + +En esta lección cubriremos: + +* [Datos estructurados y no estructurados](../../../../../3-transport/lessons/2-store-location-data) +* [Enviar datos GPS a un IoT Hub](../../../../../3-transport/lessons/2-store-location-data) +* [Rutas calientes, templadas y frías](../../../../../3-transport/lessons/2-store-location-data) +* [Manejar eventos GPS usando código sin servidor](../../../../../3-transport/lessons/2-store-location-data) +* [Cuentas de almacenamiento de Azure](../../../../../3-transport/lessons/2-store-location-data) +* [Conectar tu código sin servidor al almacenamiento](../../../../../3-transport/lessons/2-store-location-data) + +## Datos estructurados y no estructurados + +Los sistemas informáticos manejan datos, y estos datos vienen en diferentes formas y tamaños. Pueden variar desde números individuales, grandes cantidades de texto, videos e imágenes, hasta datos IoT. Los datos generalmente se dividen en una de dos categorías: *estructurados* y *no estructurados*. + +* **Datos estructurados** son datos con una estructura bien definida y rígida que no cambia, y usualmente se mapean a tablas de datos con relaciones. Un ejemplo es la información de una persona, incluyendo su nombre, fecha de nacimiento y dirección. + +* **Datos no estructurados** son datos sin una estructura bien definida y rígida, incluyendo datos que pueden cambiar de estructura frecuentemente. Un ejemplo son documentos como textos escritos o hojas de cálculo. + +✅ Investiga: ¿Puedes pensar en otros ejemplos de datos estructurados y no estructurados? + +> 💁 También existen datos semiestructurados que tienen estructura pero no encajan en tablas de datos fijas. + +Los datos IoT generalmente se consideran datos no estructurados. + +Imagina que estás añadiendo dispositivos IoT a una flota de vehículos para una gran granja comercial. Podrías querer usar diferentes dispositivos para diferentes tipos de vehículos. Por ejemplo: + +* Para vehículos agrícolas como tractores, necesitas datos GPS para asegurarte de que están trabajando en los campos correctos. +* Para camiones de reparto que transportan alimentos a almacenes, necesitas datos GPS, así como datos de velocidad y aceleración para garantizar que el conductor maneje de forma segura, además de datos de identidad del conductor y de inicio/parada para cumplir con las leyes locales sobre horas de trabajo. +* Para camiones refrigerados, también necesitas datos de temperatura para asegurarte de que los alimentos no se calienten o enfríen demasiado y se echen a perder durante el transporte. + +Estos datos pueden cambiar constantemente. Por ejemplo, si el dispositivo IoT está en la cabina de un camión, los datos que envía pueden cambiar según el remolque, por ejemplo, enviando datos de temperatura solo cuando se utiliza un remolque refrigerado. + +✅ ¿Qué otros datos IoT podrían capturarse? Piensa en los tipos de cargas que los camiones pueden transportar, así como en datos de mantenimiento. + +Estos datos varían de un vehículo a otro, pero todos se envían al mismo servicio IoT para su procesamiento. El servicio IoT necesita ser capaz de procesar estos datos no estructurados, almacenándolos de una manera que permita buscarlos o analizarlos, pero que funcione con diferentes estructuras de datos. + +### Almacenamiento SQL vs NoSQL + +Las bases de datos son servicios que permiten almacenar y consultar datos. Las bases de datos vienen en dos tipos: SQL y NoSQL. + +#### Bases de datos SQL + +Las primeras bases de datos fueron Sistemas de Gestión de Bases de Datos Relacionales (RDBMS), o bases de datos relacionales. También se conocen como bases de datos SQL debido al Lenguaje de Consulta Estructurado (SQL) utilizado para interactuar con ellas para agregar, eliminar, actualizar o consultar datos. Estas bases de datos consisten en un esquema: un conjunto bien definido de tablas de datos, similar a una hoja de cálculo. Cada tabla tiene múltiples columnas con nombres. Cuando insertas datos, agregas una fila a la tabla, colocando valores en cada una de las columnas. Esto mantiene los datos en una estructura muy rígida: aunque puedes dejar columnas vacías, si deseas agregar una nueva columna, debes hacerlo en la base de datos, rellenando valores para las filas existentes. Estas bases de datos son relacionales, en el sentido de que una tabla puede tener una relación con otra. + +![Una base de datos relacional con el ID de la tabla de usuarios relacionado con la columna de ID de usuario de la tabla de compras, y el ID de la tabla de productos relacionado con el ID de producto de la tabla de compras](../../../../../translated_images/sql-database.be160f12bfccefd3ca718a66468c2c4c89c53e5aad4c295324d576da87f9dfdd.es.png) + +Por ejemplo, si almacenas los detalles personales de un usuario en una tabla, tendrías algún tipo de ID único interno por usuario que se utiliza en una fila de una tabla que contiene el nombre y la dirección del usuario. Si luego quisieras almacenar otros detalles sobre ese usuario, como sus compras, en otra tabla, tendrías una columna en la nueva tabla para el ID de ese usuario. Cuando buscas un usuario, puedes usar su ID para obtener sus detalles personales de una tabla y sus compras de otra. + +Las bases de datos SQL son ideales para almacenar datos estructurados y para cuando deseas asegurarte de que los datos coincidan con tu esquema. + +✅ Si no has usado SQL antes, tómate un momento para leer sobre ello en la [página de SQL en Wikipedia](https://wikipedia.org/wiki/SQL). + +Algunas bases de datos SQL conocidas son Microsoft SQL Server, MySQL y PostgreSQL. + +✅ Investiga: Lee sobre algunas de estas bases de datos SQL y sus capacidades. + +#### Bases de datos NoSQL + +Las bases de datos NoSQL se llaman NoSQL porque no tienen la misma estructura rígida de las bases de datos SQL. También se conocen como bases de datos de documentos, ya que pueden almacenar datos no estructurados como documentos. + +> 💁 A pesar de su nombre, algunas bases de datos NoSQL permiten usar SQL para consultar los datos. + +![Documentos en carpetas en una base de datos NoSQL](../../../../../translated_images/noqsl-database.62d24ccf5b73f60d35c245a8533f1c7147c0928e955b82cb290b2e184bb434df.es.png) + +Las bases de datos NoSQL no tienen un esquema predefinido que limite cómo se almacenan los datos; en cambio, puedes insertar cualquier dato no estructurado, generalmente utilizando documentos JSON. Estos documentos pueden organizarse en carpetas, similar a los archivos en tu computadora. Cada documento puede tener diferentes campos en comparación con otros documentos. Por ejemplo, si estuvieras almacenando datos IoT de tus vehículos agrícolas, algunos podrían tener campos para datos de acelerómetro y velocidad, mientras que otros podrían tener campos para la temperatura en el remolque. Si agregaras un nuevo tipo de camión, como uno con básculas integradas para rastrear el peso de los productos transportados, entonces tu dispositivo IoT podría agregar este nuevo campo y podría almacenarse sin cambios en la base de datos. + +Algunas bases de datos NoSQL conocidas incluyen Azure CosmosDB, MongoDB y CouchDB. + +✅ Investiga: Lee sobre algunas de estas bases de datos NoSQL y sus capacidades. + +En esta lección, usarás almacenamiento NoSQL para guardar datos IoT. + +## Enviar datos GPS a un IoT Hub + +En la última lección capturaste datos GPS de un sensor GPS conectado a tu dispositivo IoT. Para almacenar estos datos IoT en la nube, necesitas enviarlos a un servicio IoT. Una vez más, usarás Azure IoT Hub, el mismo servicio IoT en la nube que utilizaste en el proyecto anterior. + +![Enviando telemetría GPS desde un dispositivo IoT a IoT Hub](../../../../../translated_images/gps-telemetry-iot-hub.8115335d51cd2c1285d20e9d1b18cf685e59a8e093e7797291ef173445af6f3d.es.png) + +### Tarea - enviar datos GPS a un IoT Hub + +1. Crea un nuevo IoT Hub utilizando el nivel gratuito. + + > ⚠️ Puedes consultar las [instrucciones para crear un IoT Hub del proyecto 2, lección 4](../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud/README.md#create-an-iot-service-in-the-cloud) si es necesario. + + Recuerda crear un nuevo Grupo de Recursos. Nombra el nuevo Grupo de Recursos `gps-sensor` y el nuevo IoT Hub con un nombre único basado en `gps-sensor`, como `gps-sensor-`. + + > 💁 Si aún tienes tu IoT Hub del proyecto anterior, puedes reutilizarlo. Recuerda usar el nombre de este IoT Hub y el Grupo de Recursos en el que está al crear otros servicios. + +1. Agrega un nuevo dispositivo al IoT Hub. Llama a este dispositivo `gps-sensor`. Obtén la cadena de conexión para el dispositivo. + +1. Actualiza el código de tu dispositivo para enviar los datos GPS al nuevo IoT Hub utilizando la cadena de conexión del dispositivo obtenida en el paso anterior. + + > ⚠️ Puedes consultar las [instrucciones para conectar tu dispositivo a un IoT del proyecto 2, lección 4](../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud/README.md#connect-your-device-to-the-iot-service) si es necesario. + +1. Cuando envíes los datos GPS, hazlo en formato JSON con el siguiente formato: + + ```json + { + "gps" : + { + "lat" : , + "lon" : + } + } + ``` + +1. Envía datos GPS cada minuto para no exceder tu asignación diaria de mensajes. + +Si estás utilizando el Wio Terminal, recuerda agregar todas las bibliotecas necesarias y configurar la hora utilizando un servidor NTP. Tu código también debe asegurarse de haber leído todos los datos del puerto serial antes de enviar la ubicación GPS, utilizando el código existente de la última lección. Usa el siguiente código para construir el documento JSON: + +```cpp +DynamicJsonDocument doc(1024); +doc["gps"]["lat"] = gps.location.lat(); +doc["gps"]["lon"] = gps.location.lng(); +``` + +Si estás utilizando un dispositivo IoT virtual, recuerda instalar todas las bibliotecas necesarias utilizando un entorno virtual. + +Para tanto el Raspberry Pi como el dispositivo IoT virtual, utiliza el código existente de la última lección para obtener los valores de latitud y longitud, luego envíalos en el formato JSON correcto con el siguiente código: + +```python +message_json = { "gps" : { "lat":lat, "lon":lon } } +print("Sending telemetry", message_json) +message = Message(json.dumps(message_json)) +``` + +> 💁 Puedes encontrar este código en la carpeta [code/wio-terminal](../../../../../3-transport/lessons/2-store-location-data/code/wio-terminal), [code/pi](../../../../../3-transport/lessons/2-store-location-data/code/pi) o [code/virtual-device](../../../../../3-transport/lessons/2-store-location-data/code/virtual-device). + +Ejecuta el código de tu dispositivo y asegúrate de que los mensajes estén fluyendo hacia IoT Hub utilizando el comando CLI `az iot hub monitor-events`. + +## Rutas calientes, templadas y frías + +Los datos que fluyen desde un dispositivo IoT hacia la nube no siempre se procesan en tiempo real. Algunos datos necesitan procesamiento en tiempo real, otros pueden procesarse poco tiempo después, y otros pueden procesarse mucho más tarde. El flujo de datos hacia diferentes servicios que procesan los datos en diferentes momentos se conoce como rutas calientes, templadas y frías. + +### Ruta caliente + +La ruta caliente se refiere a los datos que necesitan ser procesados en tiempo real o casi en tiempo real. Usarías datos de ruta caliente para alertas, como recibir notificaciones de que un vehículo se está acercando a un depósito o que la temperatura en un camión refrigerado es demasiado alta. + +Para usar datos de ruta caliente, tu código respondería a eventos tan pronto como sean recibidos por tus servicios en la nube. + +### Ruta templada + +La ruta templada se refiere a los datos que pueden procesarse poco tiempo después de ser recibidos, por ejemplo, para informes o análisis a corto plazo. Usarías datos de ruta templada para informes diarios sobre el kilometraje de los vehículos, utilizando datos recopilados el día anterior. + +Los datos de ruta templada se almacenan una vez que son recibidos por el servicio en la nube dentro de algún tipo de almacenamiento que pueda ser accedido rápidamente. + +### Ruta fría + +La ruta fría se refiere a datos históricos, almacenando datos a largo plazo para ser procesados cuando sea necesario. Por ejemplo, podrías usar la ruta fría para obtener informes anuales de kilometraje de vehículos o realizar análisis de rutas para encontrar la ruta más óptima y reducir costos de combustible. + +Los datos de ruta fría se almacenan en almacenes de datos: bases de datos diseñadas para almacenar grandes cantidades de datos que nunca cambiarán y que pueden ser consultados de manera rápida y sencilla. Normalmente tendrías un trabajo regular en tu aplicación en la nube que se ejecutaría a una hora regular cada día, semana o mes para mover datos del almacenamiento de ruta templada al almacén de datos. + +✅ Piensa en los datos que has capturado hasta ahora en estas lecciones. ¿Son datos de ruta caliente, templada o fría? + +## Manejar eventos GPS usando código sin servidor + +Una vez que los datos están fluyendo hacia tu IoT Hub, puedes escribir código sin servidor para escuchar eventos publicados en el punto de conexión compatible con Event-Hub. Esta es la ruta templada: estos datos serán almacenados y utilizados en la próxima lección para informes sobre el recorrido. + +![Enviando telemetría GPS desde un dispositivo IoT a IoT Hub, luego a Azure Functions mediante un disparador de Event Hub](../../../../../translated_images/gps-telemetry-iot-hub-functions.24d3fa5592455e9f4e2fe73856b40c3915a292b90263c31d652acfd976cfedd8.es.png) + +### Tarea - manejar eventos GPS usando código sin servidor + +1. Crea una aplicación de Azure Functions utilizando la CLI de Azure Functions. Usa el runtime de Python y créala en una carpeta llamada `gps-trigger`, utilizando el mismo nombre para el proyecto de la aplicación de Functions. Asegúrate de crear un entorno virtual para esto. +> ⚠️ Puedes consultar las [instrucciones para crear un proyecto de Azure Functions del proyecto 2, lección 5](../../../2-farm/lessons/5-migrate-application-to-the-cloud/README.md#create-a-serverless-application) si es necesario. +1. Agrega un desencadenador de eventos de IoT Hub que utilice el endpoint compatible con Event Hub del IoT Hub. + + > ⚠️ Puedes consultar las [instrucciones para crear un desencadenador de eventos de IoT Hub del proyecto 2, lección 5](../../../2-farm/lessons/5-migrate-application-to-the-cloud/README.md#create-an-iot-hub-event-trigger) si es necesario. + +1. Configura la cadena de conexión del endpoint compatible con Event Hub en el archivo `local.settings.json`, y utiliza la clave correspondiente en el archivo `function.json`. + +1. Usa la aplicación Azurite como emulador de almacenamiento local. + +1. Ejecuta tu aplicación de funciones para asegurarte de que está recibiendo eventos desde tu dispositivo GPS. Asegúrate de que tu dispositivo IoT también esté funcionando y enviando datos GPS. + + ```output + Python EventHub trigger processed an event: {"gps": {"lat": 47.73481, "lon": -122.25701}} + ``` + +## Cuentas de Almacenamiento de Azure + +![El logotipo de Azure Storage](../../../../../translated_images/azure-storage-logo.605c0f602c640d482a80f1b35a2629a32d595711b7ab1d7ceea843250615ff32.es.png) + +Las Cuentas de Almacenamiento de Azure son un servicio de almacenamiento de propósito general que puede almacenar datos de diversas maneras. Puedes almacenar datos como blobs, en colas, en tablas o como archivos, y todo al mismo tiempo. + +### Almacenamiento de blobs + +La palabra *Blob* significa objetos binarios grandes, pero se ha convertido en el término para cualquier dato no estructurado. Puedes almacenar cualquier dato en el almacenamiento de blobs, desde documentos JSON que contienen datos de IoT, hasta archivos de imágenes y películas. El almacenamiento de blobs tiene el concepto de *contenedores*, que son como carpetas nombradas donde puedes almacenar datos, similar a las tablas en una base de datos relacional. Estos contenedores pueden tener una o más carpetas para almacenar blobs, y cada carpeta puede contener otras carpetas, similar a cómo se almacenan los archivos en el disco duro de tu computadora. + +Usarás el almacenamiento de blobs en esta lección para almacenar datos de IoT. + +✅ Investiga: Lee sobre el [Almacenamiento de Blobs de Azure](https://docs.microsoft.com/azure/storage/blobs/storage-blobs-overview?WT.mc_id=academic-17441-jabenn) + +### Almacenamiento de tablas + +El almacenamiento de tablas te permite almacenar datos semiestructurados. El almacenamiento de tablas es en realidad una base de datos NoSQL, por lo que no requiere un conjunto definido de tablas de antemano, pero está diseñado para almacenar datos en una o más tablas, con claves únicas para definir cada fila. + +✅ Investiga: Lee sobre el [Almacenamiento de Tablas de Azure](https://docs.microsoft.com/azure/storage/tables/table-storage-overview?WT.mc_id=academic-17441-jabenn) + +### Almacenamiento de colas + +El almacenamiento de colas te permite almacenar mensajes de hasta 64 KB de tamaño en una cola. Puedes agregar mensajes al final de la cola y leerlos desde el principio. Las colas almacenan mensajes indefinidamente mientras haya espacio de almacenamiento disponible, lo que permite que los mensajes se almacenen a largo plazo y se lean cuando sea necesario. Por ejemplo, si quisieras ejecutar un trabajo mensual para procesar datos GPS, podrías agregar mensajes a una cola todos los días durante un mes y luego, al final del mes, procesar todos los mensajes de la cola. + +✅ Investiga: Lee sobre el [Almacenamiento de Colas de Azure](https://docs.microsoft.com/azure/storage/queues/storage-queues-introduction?WT.mc_id=academic-17441-jabenn) + +### Almacenamiento de archivos + +El almacenamiento de archivos es el almacenamiento de archivos en la nube, y cualquier aplicación o dispositivo puede conectarse utilizando protocolos estándar de la industria. Puedes escribir archivos en el almacenamiento de archivos y luego montarlo como una unidad en tu PC o Mac. + +✅ Investiga: Lee sobre el [Almacenamiento de Archivos de Azure](https://docs.microsoft.com/azure/storage/files/storage-files-introduction?WT.mc_id=academic-17441-jabenn) + +## Conecta tu código sin servidor al almacenamiento + +Tu aplicación de funciones ahora necesita conectarse al almacenamiento de blobs para almacenar los mensajes del IoT Hub. Hay dos maneras de hacerlo: + +* Dentro del código de la función, conecta al almacenamiento de blobs utilizando el SDK de Python para blobs y escribe los datos como blobs. +* Usa un enlace de salida de función para vincular el valor de retorno de la función al almacenamiento de blobs y que el blob se guarde automáticamente. + +En esta lección, usarás el SDK de Python para ver cómo interactuar con el almacenamiento de blobs. + +![Enviando telemetría GPS desde un dispositivo IoT a IoT Hub, luego a Azure Functions a través de un desencadenador de Event Hub, y luego guardándolo en el almacenamiento de blobs](../../../../../translated_images/save-telemetry-to-storage-from-functions.ed3b1820980097f143d9f0570072da11304c2bc7906359dfa075b4d9b253c20f.es.png) + +Los datos se guardarán como un blob JSON con el siguiente formato: + +```json +{ + "device_id": , + "timestamp" :