如何无缝扩展 ThingsBoard 功能？原来二次开发如此简单！
众所周知，ThingsBoard 核心采用 Spring Boot 开发，当然，很多人已经在 Spring Boot 之上平步青云，那如何无缝扩展 ThingsBoard 功能，而不改变原有代码结构，且将来无缝升级？ 如果你有 ThingsBoard 服务需求或二次开发需求，请与我们联系： 18616669123 关注我们 关注 ThingsBoard 微信公众号 手动增加微信公众号：thingsboard_cn 访问 ThingsBoard 中文社区网站 访问网址：http://www.thingsboard.club 创建自定义 Spring Boot Starter，实现功能模块 新建 Spring Boot Starter 项目 名称定义为了方便识别： xxx-xxx-spring-boot-starter ![project.png][3] 增加依赖，看需求，自己的项目需要，spring-boot-autoconfigure，必不可少！ ![depends.png][4] 完整pom.xml，自己细品 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath /> </parent> <groupId>cn.yiqisoft</groupId> <artifactId>report-spring-boot-starter</artifactId> <version>0.0.1</version> <name>EcolabReport</name> <description>Ecolab Report</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> ## 新建controller，为了方便测试，简单即可 - 新建 controller 文件 package cn.yiqisoft.ecolabanalysis.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class ReportController { @RequestMapping(value = "/api/report", method = RequestMethod.GET) public String reportList() { return "Report List"; } } ## 自动装载工程 - 新建 src/main/resources/META-INF/spring.factories 文件 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ cn.yiqisoft.ecolabanalysis.controller.ReportController - 通知 Spring Boot 启动时自动装载我们的 Controller ## 打包，jar 包输出 命令行编译，并安装到本地 maven 库 mvn clean install 生成 ～/.m2/repository/cn/yiqisoft/report-spring-boot-starter/0.0.1/ecolab-report-spring-boot-starter-0.0.1.jar，这样本地其他项目依赖此 jar 包即可。 ## 【可选】本地运行项目，独立测试都没问题 命令行启动项目 mvn spring-boot:run 效果 jiekechoo@jiekechoo ~ % curl http://localhost:8080/api/report Report List jiekechoo@jiekechoo ~ % # 融入 ThingsBoard ，实现无缝二次开发 ## 自定义 starter 分析 - 我们的 maven 库 <groupId>cn.yiqisoft</groupId> <artifactId>report-spring-boot-starter</artifactId> <version>0.0.1</version> - 加入 ThingsBoard application 工程依赖，在 application/pom.xml 加入我们的 maven 库即可 ![pom.png][5] ## 运行 ThingsBoard application 工程 - 打开 swagger ，我们二次开发的模块已经被成功载入 ![swagger.png][6] ## 扩展 - 即使 ThingsBoard 升级，我们单独 jar 包也相应升级即可； - 独立使用自己的二次开发数据库表，不影响 TB 本身； - 如果有能力，将自定义 jar 做成动态加载，实现更高级别。 # 关于 亿琪软件 上海亿琪软件有限公司成立于2016年，专注于 5G 通信、AI 人工智能、边缘计算和大数据网络安全多项技术领域，致力于物联网领域前沿技术的创新，为用户提供全方位、智能化和安全的物联网解决方案。 2023年，公司发布“YiFUSION｜工业边缘智能融合一体机”产品，为工业客户提供一整套的边缘计算+AI能力：高性能数据采集、多类型数据融合、AI算法集成、云端业务对接。在边缘网关的基础上，集成了 IoT 平台的边缘协同能力、本地Web SCADA 和 HMI 功能、本地数据存储、边缘 AI 视频分析、行业应用集成等。 2022年公司推出 “YiCLOUD｜亿琪云”一站式物联网应用解决方案。公司的业务涵盖了智慧城市、智慧农业、智能工厂和智慧园区等多个领域，公司软硬件产品和解决方案获得华为技术认证，得到中国移动OCP认证，公司还是边缘计算产业联盟ECC成员。 感知物联，畅快无限。 联系我们 网站：http://yiqisoft.cn 邮件：support@yiqisoft.cn 电话：021-68863086 手机：186-1666-9123 [1]: https://www.yiqisoft.cn/blogs/usr/uploads/2023/10/2404940997.png [2]: https://www.yiqisoft.cn/blogs/usr/uploads/2023/10/2925476062.png [3]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/1800199431.png [4]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/2247303675.png [5]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/3476619080.png [6]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/1780987658.png
本文所有内容都来自原创，思路开阔，敢想敢做，经过不懈努力，终于成功扩展 ThingsBoard 功能模块 如果你有 ThingsBoard 服务需求或二次开发需求，请与我们联系： 18616669123 先来看一段视频，体验一下新增的功能，前端增加的菜单和功能演示。 关注我们 关注 ThingsBoard 微信公众号 手动增加微信公众号：thingsboard_cn 访问 ThingsBoard 中文社区网站 访问网址：http://www.thingsboard.club 前言 此次二次开发，主要是针对 ThingsBoard 新增功能模块，以报表功能为目的，提供一个可以独立与原有功能的 Report/报表 模块，咱们先这么来定义。就像 Device/设备、Asset/资产模块，增删改查必不可少，还需要兼容 ThingsBoard 原有操作习惯，还可以将 Report/报表 分配给特定的 Customer/客户。上图，这是开始的设想： 后端 代码结构 modified: application/src/main/java/org/thingsboard/server/controller/BaseController.java new file: application/src/main/java/org/thingsboard/server/controller/ReportController.java modified: application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java modified: application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java modified: application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java modified: application/src/main/resources/thingsboard.yml new file: common/dao-api/src/main/java/org/thingsboard/server/dao/report/ReportService.java modified: common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java modified: common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java new file: common/data/src/main/java/org/thingsboard/server/common/data/Report.java new file: common/data/src/main/java/org/thingsboard/server/common/data/ReportInfo.java modified: common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java new file: common/data/src/main/java/org/thingsboard/server/common/data/id/ReportId.java modified: common/data/src/main/java/org/thingsboard/server/common/data/query/EntityFilterType.java new file: common/data/src/main/java/org/thingsboard/server/common/data/query/ReportSearchQueryFilter.java new file: common/data/src/main/java/org/thingsboard/server/common/data/query/ReportTypeFilter.java new file: common/data/src/main/java/org/thingsboard/server/common/data/report/ReportSearchQuery.java new file: dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractReportEntity.java new file: dao/src/main/java/org/thingsboard/server/dao/model/sql/ReportEntity.java new file: dao/src/main/java/org/thingsboard/server/dao/model/sql/ReportInfoEntity.java new file: dao/src/main/java/org/thingsboard/server/dao/report/ReportDao.java new file: dao/src/main/java/org/thingsboard/server/dao/report/ReportServiceImpl.java modified: dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java modified: dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java new file: dao/src/main/java/org/thingsboard/server/dao/sql/report/JpaReportDao.java new file: dao/src/main/java/org/thingsboard/server/dao/sql/report/ReportRepository.java modified: pom.xml 根据 git 提供的log，看出来新增文件比修改文件多，也是此次二次开发的难点所在。 新增文件：新增的文件主要以扩展功能模块为主，大概是这样：POJO（DTO，ID），Entity，Repository，Dao，Service/Impl，Controller，基本都是依葫芦画瓢； 修改文件：因为要达到 ThingsBoard 原有的一些功能体验，势必要满足其实现逻辑，那就是找到所有的 Device 功能模块的做法，在所有需要的地方增加 Report 功能，无非就是一些新增枚举值，方法调用，新增 case 判断； 这个开发过程中，我发现，频繁读取一些 API，且都是需要数据库交互，如果用户数量大，不是一个好方法，这里举一个例子： 获取实体类型频繁数据库交互 调用后台 API 为： /api/report/types，追查代码发现其实是一次 SELECT，瞬间尴尬了 @Query("SELECT DISTINCT d.type FROM ReportEntity d WHERE d.tenantId = :tenantId") List<String> findTenantReportTypes(@Param("tenantId") UUID tenantId); WEB API，大概就是把 device 都替换成了 report，其他逻辑上没有做更改，为了配合前端的调用，这些都是必不可少的内容。因为用 device 衍生过来，把 cridentail 相关内容删除了。 数据表 CREATE TABLE public.report ( id uuid NOT NULL, created_time bigint NOT NULL, additional_info character varying COLLATE pg_catalog."default", customer_id uuid, type character varying(255) COLLATE pg_catalog."default", name character varying(255) COLLATE pg_catalog."default", label character varying(255) COLLATE pg_catalog."default", search_text character varying(255) COLLATE pg_catalog."default", tenant_id uuid, CONSTRAINT report_pkey PRIMARY KEY (id), CONSTRAINT report_name_unq_key UNIQUE (tenant_id, name) ) 如果你观察仔细，发现跟 device 表几乎一样，那是因为我们以 device 为原型做的二次开发。开发自己功能时，表的定义请随意啊。不过，name, type, search_text, id, customer_id, tenant_id, create_time 都是不能少的，因为框架业务逻辑有代码实现一些功能； 建议增加几个不影响 ThingsBoard 框架工作的“扩展字段”，也可以直接使用 additional_info 来存储自己的数据，这个字段最长可以有 1G，足够放你需要的结构化或非结构化数据；类似：{ "hello": "world", "thingsboard": "iot", "company": "yiqisoft", "location": "shanghai", "protocol": ["coap", "mqtt", "http"] } 自由业务逻辑，针对“扩展字段”的操作，请随意，数据频繁修改的还是用自己的业务表，不要混为一谈。 业务逻辑实现 对于自己的业务逻辑开发方面，建议不要改动 ThingsBoard 的代码结构，可以使用外挂一个 jar，来独立实现业务功能，这个具体要看业务复杂度，是不是需要与 ThingsBoard 耦合，可以查看前期我们发布的文章：如何无缝扩展 ThingsBoard 功能？原来二次开发如此简单！ ， 如何无缝扩展 ThingsBoard 功能？原来二次开发如此简单！【续】 前端 代码结构 modified: ui-ngx/src/app/core/http/entity.service.ts new file: ui-ngx/src/app/core/http/report.service.ts modified: ui-ngx/src/app/core/services/menu.service.ts modified: ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts modified: ui-ngx/src/app/modules/home/dialogs/add-entities-to-customer-dialog.component.ts modified: ui-ngx/src/app/modules/home/dialogs/assign-to-customer-dialog.component.ts modified: ui-ngx/src/app/modules/home/dialogs/home-dialogs.service.ts modified: ui-ngx/src/app/modules/home/pages/customer/customer-routing.module.ts modified: ui-ngx/src/app/modules/home/pages/customer/customer.component.html modified: ui-ngx/src/app/modules/home/pages/customer/customers-table-config.resolver.ts modified: ui-ngx/src/app/modules/home/pages/home-pages.module.ts new file: ui-ngx/src/app/modules/home/pages/report/report-routing.module.ts new file: ui-ngx/src/app/modules/home/pages/report/report-table-header.component.html new file: ui-ngx/src/app/modules/home/pages/report/report-table-header.component.scss new file: ui-ngx/src/app/modules/home/pages/report/report-table-header.component.ts new file: ui-ngx/src/app/modules/home/pages/report/report-tabs.component.html new file: ui-ngx/src/app/modules/home/pages/report/report-tabs.component.ts new file: ui-ngx/src/app/modules/home/pages/report/report.component.html new file: ui-ngx/src/app/modules/home/pages/report/report.component.scss new file: ui-ngx/src/app/modules/home/pages/report/report.component.ts new file: ui-ngx/src/app/modules/home/pages/report/report.module.ts new file: ui-ngx/src/app/modules/home/pages/report/reports-table-config.resolver.ts modified: ui-ngx/src/app/shared/components/entity/entity-autocomplete.component.ts modified: ui-ngx/src/app/shared/components/entity/entity-subtype-autocomplete.component.ts modified: ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts modified: ui-ngx/src/app/shared/components/entity/entity-subtype-select.component.ts modified: ui-ngx/src/app/shared/components/footer.component.html modified: ui-ngx/src/app/shared/models/alias.models.ts modified: ui-ngx/src/app/shared/models/entity-type.models.ts new file: ui-ngx/src/app/shared/models/id/report-id.ts new file: ui-ngx/src/app/shared/models/report.models.ts modified: ui-ngx/src/assets/locale/locale.constant-en_US.json modified: ui-ngx/src/assets/locale/locale.constant-zh_CN.json modified: ui-ngx/src/assets/logo_title_white.svg modified: ui-ngx/src/environments/environment.prod.ts modified: ui-ngx/src/environments/environment.ts modified: ui-ngx/src/index.html new file: ui-ngx/src/yiqisoft.ico 先复制一份 ui-ngx/src/app/modules/home/pages/device 到 ui-ngx/src/app/modules/home/pages/report，就是组件要完整，文件名都改掉，内部都是替换操作： Device -> Report, device -> report, DEVICE -> REPORT，这样我们的 ReportModule 就做好了； 在 home-pages.module.ts 载入 ReportModule ； 在 ui-ngx/src/app/core/services/menu.service.ts 增加需要的菜单； 根据 report 目录里面的内容，需要从 device 功能模块复制一些组件和 service，挺多的，自己慢慢找，也算是熟悉一下前端代码； 汉化，就是修改 ui-ngx/src/assets/locale/ 目录下相应的语言包，很容易； 功能扩展过程 前期，我们发布了文章，如何进行 ThingsBoard 前端二次开发？超强 Angular 框架帮你忙。，介绍如果用 Angular 二次开发的要点，具体看开发者对于 Angular 框架掌握程度。 功能扩展建议 像上面的实体类型获取，增加功能特别不容易，因为代码实现是通过枚举值来 switch/case 来判断，那么新增功能模块时，需要改动太大了，如果能够独立到每个功能模块的组件中，那就方便多了。但是，前端代码就会有很多重复。为了扩展 REPORT，必须要找到所有的 case，上代码： switch (entity.id.entityType as EntityType | string) { case 'function': materialIcon = 'functions'; break; case EntityType.DEVICE: materialIcon = 'devices_other'; break; case EntityType.REPORT: materialIcon = 'equalizer'; break; case EntityType.ASSET: materialIcon = 'domain'; break; } 更改 LOGO，需要使用工具做一个 svg 矢量图，替换 ui-ngx/src/assets/logo_title_white.svg 即可； 更改 Swagger 显示内容需要改 thingsboard.yml； 欢迎大家一起来加入 ThingsBoard 讨论，可以在下方留言给作者。其实，我是最不建议在 ThingsBoard 上改动，我崇尚无缝扩展，但是太难了，所以才有了本文的发表，把自己的业务融入进去是一次尝试。当然，有能力的朋友可以自己独立做业务系统，对于简单物联网应用，何必重复制造轮子呢？
如何无缝扩展 ThingsBoard 功能？原来二次开发如此简单！【续1】
目录 关注我们 关注 ThingsBoard 微信公众号 访问 ThingsBoard 中文社区网站 前期，发表过多个系列文章关于如何无缝扩展 ThingsBoard 功能，其实在实施过程中，还是遇到很多问题，需要提前注意！ 独立于 ThingsBoard 外的功能模块注意要点 关注我们 关注 ThingsBoard 微信公众号 手动增加微信公众号：thingsboard_cn 访问 ThingsBoard 中文社区网站 访问网址：http://www.thingsboard.club 前期，发表过多个系列文章关于如何无缝扩展 ThingsBoard 功能，其实在实施过程中，还是遇到很多问题，需要提前注意！ 如果你有 ThingsBoard 服务需求或二次开发需求，请与我们联系： 18616669123 独立于 ThingsBoard 外的功能模块注意要点 功能模块需要能够独立运行，不管是服务也好，controller 也罢，都要能够正常运行，就类似单元测试跑通，才可以融入到 ThingsBoard 中； 数据表要独立成 sql 文件，便于移植到 ThingsBoard 库中，最好不要跟原有数据表有关联或冲突，尤其不能冲突； 调用系统库表，新建的 Entity 要注意 column 名字于原有一样，使用 @Column(name = "foo_bar")，否则 Bean 建立失败； 如果 Entity 有嵌套调用 POJO，需要将 Entity 设置成 @Proxy(lazy = false)，关闭懒加载，否则无法查询数据； 打包功能模块，需要将 Spring Boot 项目 target 中的 .original 文件安装到本地 maven 库，或者修改 pom.xml 文件来改变 maven 打包规则； 功能模块中的附件，图片，pdf 模板，直接在功能模块 jar 包中，不需要单独导入 ThingsBoard 中； Controller 要单独命名，不能与 ThingsBoard 冲突，API 路径可以复用原有路径，比如：原有是 /api/report/foo，可以增加新的 /api/report/bar； Domain/POJO/Repository等，要独立命名，因为我们以 maven jar 包方式融入 ThingsBoard，都交给 spring 来管理，所以命名要独立；
开源｜ThingsBoard 项目实施及二次开发要点总结
目录 关注我们 关注 ThingsBoard 微信公众号 访问 ThingsBoard 中文社区网站 Thingsboard 项目实施 实施准备 实施要点 总结经验 Thingsboard 二次开发提示 前提 技术栈 尝试 运用技巧 关于 亿琪软件 关注我们 关注 ThingsBoard 微信公众号 手动增加微信公众号：thingsboard_cn 访问 ThingsBoard 中文社区网站 访问网址：http://www.thingsboard.club 最近在实施 ThingsBoard 项目中遇到一些问题总结，还有针对 Thingsboard 二次开发中的提示。 如果你正准备使用 Thingsboard 开源框架作为你的物联网平台来使用，这个文章对你应该有一定帮助。关于 Thingsboard 平台的介绍和基础不是本文的重点，所以，你在阅读本文时，应该具备一些 Thingsboard、物联网平台、MQTT、HTTP、物模型，等基础能力。还有，如果你要实施一套自己的物联网应用，可以参考这个文章：分享｜如何组建一个项目团队来完成物联网应用？ Thingsboard 项目实施 实施准备 统计你所在网络里面的设备、资产、测点、指标、通讯方式、状态等基础信息，可以统计一些信息形成 Excel 表格，越详细越好，多多益善； 基于你对物联网的了解，要把业务结合进来，综合考虑物联网平台到底对你的业务有什么帮助，比如：信息及时性？数据总量？统计分析？降本增效？还是有其他非技术目的？ 要有相关的技术储备，人员储备，还有资金储备，毕竟还是需要不少时间、精力、金钱和欲望投入在里面； 不管如何，你还是应该准备找一个合作伙伴，能够帮助你解决一些你无法预料到的问题，以解燃眉之急； IoT、物联网、平台，这些都是基础设施，并不能完全解决你的所有问题，要摆正 Thingsboard 在你的业务中的正确位置； 至于 Thingsboard 能帮到你什么，能做什么，有什么效果，你可以在本技术博客寻找你的答案，或到互联网找到你所需要的内容； 实施要点 这里以一个工业物联网平台为例，简单介绍一些要点供你参考： 目的：工业物联网平台，当然是为了工业生产服务，例如：这个指标采集上来，频率是多少，数据变化起到什么业务帮助。如果存粹为了做一个物联网平台而做一个，那就无所谓了，只要看上去像个平台，数据在变化，有图有真相，那也行； 方法：典型的实施方法，无非就是采集、汇聚、存储、分析，方法在不同的客户有不同的操作方式，比如：改造老平台是一种有据可循的，推翻老平台又是另一个，还有新建平台也是一脸茫然，不知所措；要根据实际的需求，制定适合自己的实施方法； 过程：来举例说明一个客户的实施过程：在这个客户而已，开源是开放的，免费的，没什么难度的，所以把实施过程简单理解为：1、安装；2、配置；3、调整；4、交付。我把其过程形容为：陷入泥潭的人，越陷越深，最后有可能会失败； 时间：有些客户觉得拿来即用，更何况 Thingsboard 是开源的，那就是多简单的事，其实，我们实施过的项目中，客户越是觉得简单的快速的，都会导致项目延迟，他们忽略了开源并不是你什么也不需要做就可以完成所有实施，赶工期不太适合用 Thingsboard 来做，假如你对开源真的有所了解的话；如果你觉得一个月能搞定，我建议你把时间放大到3个月，中间你会遇到太多的疑问和不知道，如果有合作伙伴能帮你，那你算是幸运儿，有些自己几个星期搞不定的问题，专业人士只需要十分钟； 效果：不要对项目实施的结果报以太多的期望，毕竟 Thingsboard 还有 PE 专业版在那里，开源版本只是提供了基础功能，的确可以让你达到完成一个物联网平台的概念，但是，需要太多的工作量去完善你的业务需求了，效果因人而异，各说纷云。 总结经验 开源贡献：如果你了解开源，你就知道开源不仅仅是索取，也需要贡献，如果你的实施过程中修复的问题并没有得到开源社区的合并，那么说明你以后需要一直去修改它，那是非常不利的局面，所以，建议你参与社区，参与贡献，对你长期使用 Thingsboard 是有帮助的而无害的； 可移植脚本：大版本不变化的情况下，你要尽量综合项目实施过程中的可复用脚本，这样，你在其他项目中就是亮点也是赢利点，这一点是很多实施者所忽视的地方； 形成标杆：一旦你发现客户的思路很有效果，你帮助客户实施完成，且具备一定的效益，你要知道这就是果实，要动得举一反三，运用到其他的客户那里，形成标杆项目，推广下去，毕竟复制/粘贴的成本是最低的。 Thingsboard 二次开发提示 前提 技术栈 其实就下面俩，你要突破的地方，我觉得应该就是 Angular 框架。如果你研究过 Thingsboard 源码，我的意思是你熟读多次，编译N次，简单开发过几次，你就应该明白其实很简单，只是代码量有点大，几个月应该是搞不定了，你不能放弃，如果你决定要进行二次开发，可以参考本技术博客的其他文章。 Java/Spring Boot/Postgresql Typescript/Angular/Javascript/HTML 尝试 作为一个开发者，我建议你最应该看的就是官方文档，不管你的英文能力怎么样，都应该找方法去尝试读他们的文档（虽然都是乌克兰写的）。 编译通过，这是首要条件，否则你的二次开发就此打住； 遵循其编码和框架规则，不要试图去改造它，你可能还不具备这个能力； 后端代码我觉得是非常简单且方便改造的，但是，前段代码所使用的 Angular 在国内并不主流，这也是很多开发者宁愿用其他前端框架重写，也不愿意改官方代码的原因吧； 一切二次开发都是需要基于业务需要而做的，那么就仔细分析一下业务，结合你现有的能力，首先尝试配置它而不是二次开发，以我们的经验，绝大部分需求都是可以通过配置（前端，也需要写一些 JS 代码，而且必须遵循其框架）来完成的。 运用技巧 首先就是官方文档，有些内容都是以简单的表格列出，其实可以算是设计说明书，非常有帮助； Github issue， 你要经常看，最好能翻边你所关注的所有，里面的答案比代码和文档更加清晰； 关注本技术博客的内容，与笔者沟通，把你需要的疑问提出来，我们专门针对问题解答（技术交流不收费）； 关于 亿琪软件 上海亿琪软件有限公司成立于2016年，专注于 5G 通信、AI 人工智能、边缘计算和大数据网络安全多项技术领域，致力于物联网领域前沿技术的创新，为用户提供全方位、智能化和安全的物联网解决方案。 2023年，公司发布“YiFUSION｜工业边缘智能融合一体机”产品，为工业客户提供一整套的边缘计算+AI能力：高性能数据采集、多类型数据融合、AI算法集成、云端业务对接。在边缘网关的基础上，集成了 IoT 平台的边缘协同能力、本地Web SCADA 和 HMI 功能、本地数据存储、边缘 AI 视频分析、行业应用集成等。 2022年公司推出 “YiCLOUD｜亿琪云”一站式物联网应用解决方案。公司的业务涵盖了智慧城市、智慧农业、智能工厂和智慧园区等多个领域，公司软硬件产品和解决方案获得华为技术认证，得到中国移动OCP认证，公司还是边缘计算产业联盟ECC成员。 感知物联，畅快无限。 联系我们 网站：http://yiqisoft.cn 邮件：support@yiqisoft.cn 电话：021-68863086 手机：186-1666-9123
此二次开发主要是基于 ThingsBoard UI 界面上的 js 脚本开发，熟悉 js 开发的朋友应该很容易理解。 从 Dashboard 导出 csv 其实有好几种情况，1是 telemetry 数据导出，2是 attributes 数据导出。 如果你有 ThingsBoard 服务需求或二次开发需求，请与我们联系： 18616669123 目录 关注我们 关注 ThingsBoard 微信公众号 访问 ThingsBoard 中文社区网站 准备工作 新建Dashboard Telemetry 数据导出 Attributes 数据导出 关注我们 关注 ThingsBoard 微信公众号 手动增加微信公众号：thingsboard_cn 访问 ThingsBoard 中文社区网站 访问网址：http://www.thingsboard.club 准备工作 Chrome 浏览器 javascript 基础知识 ThingsBoard UI 二次开发基础知识 Dashbaord 开发经验 新建Dashboard Telemetry 数据导出 导出csv文件内容： timestamp,GasCon 2022-3-21 21:29:0,800 2022-3-21 21:44:0,800 2022-3-25 19:59:0,0 自定义 action，js脚本： let $injector = widgetContext.$scope.$injector; let attributeService = $injector.get(widgetContext .servicesMap.get('attributeService')); let deviceService = $injector.get(widgetContext.servicesMap .get('deviceService')); console.log(widgetContext); let data = widgetContext.data; let dataKeys = []; // get all data keys to array widgetContext.datasources[0].dataKeys.forEach(function( item) { dataKeys.push(item.name); }); let fileTitle = "export-from-list-" + entityName; function timeConverter(UNIX_timestamp) { var a = new Date(UNIX_timestamp); var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]; var year = a.getFullYear(); var month = a.getMonth()+1; var date = a.getDate(); var hour = a.getHours(); var min = a.getMinutes(); var sec = a.getSeconds(); var time = year + '-' + month + '-' + date + ' ' + hour + ':' + min + ':' + sec; return time; } function exportCSV() { // first line: header var allLine = ""; dataKeys.unshift("timestamp"); allLine += dataKeys; allLine += "\n"; var key_length = data.length; // 字段数目 var limit = data[0]["data"].length; // 数据行数 var line = new Array(limit + 1); // 包括首行 for (var l = 0; l < limit; l++) line[l] = ""; data.forEach( (item, idx) => { var item_data = item["data"]; var dataKey = item["dataKey"]; for (var j = 0; j < limit; j++) { if (idx == 0) { line[j] += timeConverter(item_data[ j][0]); line[j] += ","; } line[j] += item_data[j][1]; if (idx < key_length - 1) line[j] += ","; } line[j] += "\n"; } ); for (var k = 0; k < limit; k++) { allLine += line[k]; allLine += "\n"; } var exportedFilenmae = fileTitle + '.csv' || 'export.csv'; var blob = new Blob([allLine], { type: 'text/csv;charset=utf-8;' }); if (navigator.msSaveBlob) { // IE 10+ navigator.msSaveBlob(blob, exportedFilenmae); } else { var link = document.createElement("a"); if (link.download !== undefined) { // feature detection // Browsers that support HTML5 download attribute var url = URL.createObjectURL(blob); link.setAttribute("href", url); link.setAttribute("download", exportedFilenmae); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } } } exportCSV(); Attributes 数据导出 导出csv文件内容： timestamp,name,detector_tag,area,floor,location,department,equipment_name,gas,setup_date,sensor_date,cal_date,cal_result,ip,hub_port,sub_hub_port,maintenance 2022-3-28 21:25:9,CL96-06,,,,,,,,,,,,,,, 2022-3-28 21:25:9,F-CL96-SRD013-HF,,,,,,,,,,,,,,, 2022-3-28 21:25:9,F-CL96-SRD033-C-NH3,,,,,,,,,,,,,,, 2022-3-28 21:25:9,F-CL96-SRD033-D-NH3,,,,,,,,,,,,,,, 2022-3-28 21:25:9,F-CL96-SRD037-CLF3,,,,,,,,,,,,,,, 自定义 action，js 脚本： let $injector = widgetContext.$scope.$injector; let attributeService = $injector.get(widgetContext .servicesMap.get('attributeService')); let deviceService = $injector.get(widgetContext.servicesMap .get('deviceService')); let data = widgetContext.data; console.log(data); let dataKeys = []; // get all data keys to array widgetContext.datasources[0].dataKeys.forEach(function( item) { dataKeys.push(item.name); }); let fileTitle = "export-device-list"; function timeConverter(UNIX_timestamp) { var a = new Date(UNIX_timestamp); var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]; var year = a.getFullYear(); var month = a.getMonth()+1; var date = a.getDate(); var hour = a.getHours(); var min = a.getMinutes(); var sec = a.getSeconds(); var time = year + '-' + month + '-' + date + ' ' + hour + ':' + min + ':' + sec; return time; } function exportCSV() { // first line: header var allLine = ""; var key_length = dataKeys .length; // csv字段数目, 不含timestamp dataKeys.unshift("timestamp"); allLine += dataKeys; // allLine += "\n"; var limit = data.length / key_length; // csv数据行数 var line = new Array(limit + 1); // csv总行数，包括首行 for (var l = 0; l < limit; l++) line[l] = ""; //var j = 0; data.forEach( (item, idx) => { var item_data = item["data"]; if (idx % key_length == 0) { allLine += "\n"; // 换行 allLine += timeConverter(item_data[0][0]); // timestamp allLine += ","; } allLine += item_data[0][1]; // value/值 if ((idx+1) % key_length != 0) allLine += ","; } ); allLine += "\n"; // for (var k = 0; k < key_length; k++) { // allLine += line[k]; // allLine += "\n"; // } var exportedFilenmae = fileTitle + '.csv' || 'export.csv'; var blob = new Blob([allLine], { type: 'text/csv;charset=utf-8;' }); if (navigator.msSaveBlob) { // IE 10+ navigator.msSaveBlob(blob, exportedFilenmae); } else { var link = document.createElement("a"); if (link.download !== undefined) { // feature detection // Browsers that support HTML5 download attribute var url = URL.createObjectURL(blob); link.setAttribute("href", url); link.setAttribute("download", exportedFilenmae); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } } } exportCSV();
2021.8.14 第一时间将 TB 3.3 的 OTA 功能进行源码分析，基本思路就是 应用了telemetry 和 attributes ，不复杂，自己实现的话也是要这样来做。这里，只是分析了 CoAP 协议层，其他类似。 如果你有 ThingsBoard 服务需求或二次开发需求，请与我们联系： 18616669123 目录 关注我们 关注 ThingsBoard 微信公众号 访问 ThingsBoard 中文社区网站 1、CoAP 路径： 2、checksum算法 3、OTA Dashboard 4、OTA 固件存储 5、测试脚本 5、升级步骤 关注我们 关注 ThingsBoard 微信公众号 手动增加微信公众号：thingsboard_cn 访问 ThingsBoard 中文社区网站 访问网址：http://www.thingsboard.club 1、CoAP 路径： 按照官方文档里面的路径是错误的，需要改成如下url路径才能获取固件：coap://localhost/fw/$access_token?title=$title&version=$versoin 具体文件位置： /common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java 2、checksum算法 默认支持 SHA256，如果设备端不支持或有其他算法请自取 enum 里面内容。 /common/data/src/main/java/org/thingsboard/server/common/data/ota/ChecksumAlgorithm.java public enum ChecksumAlgorithm { MD5, SHA256, SHA384, SHA512, CRC32, MURMUR3_32, MURMUR3_128 } 3、OTA Dashboard 自带了两个不错的查看 OTA 的dashboard，赶紧收藏起来。 firmware： /application/src/main/data/json/demo/dashboards/firmware.json software： /application/src/main/data/json/demo/dashboards/software.json 4、OTA 固件存储 firmware / software 文件使用 oid 格式存储，隐藏列，无法查看，具体详细内容请自行查看postgresql oid数据类型。 5、测试脚本 https://thingsboard.io/docs/user-guide/resources/firmware/ 目录下 http_firmware_client.py mqtt_firmware_client.py coap_firmware_client.py 基本可以用，但是脚步写的不是很好，有能力的可以自己改。 5、升级步骤 1、服务有一个属性，标记是不是要升级，设备定期去获取这个属性，有的话就下载，提交服务器“下载中”； 2、固定地址下载：包括固件名字和版本号，下载完成：提交服务器“已下载”； 3、设备验证固件包完整性，提交服务器“已验证”； 4、设备开始更新前，提交服务器“更新中”； 5、设备更新完成后，成功提交“已更新”，失败提交“失败”；
如何在 ThingsBoard 前端增加手写签名，并且体现在报告中？
目录 关注我们 关注 ThingsBoard 微信公众号 访问 ThingsBoard 中文社区网站 准备工作 增加签名用的 signature pad 包 新增用于签名的组建 新增配套 service 处理 后端图片处理 代码示例 TS 文件 HTML 文件 结果展示 关注我们 关注 ThingsBoard 微信公众号 手动增加微信公众号：thingsboard_cn 访问 ThingsBoard 中文社区网站 访问网址：http://www.thingsboard.club 准备工作 当然，首先必须要有 ThingsBoard 二次开发基础，可以在本博客中搜索“二次开发”，你会得到很多提升。 如果你有 ThingsBoard 服务需求或二次开发需求，请与我们联系： 18616669123 增加签名用的 signature pad 包 https://www.npmjs.com/package/angular2-signaturepad，根据提示，加入到 package.json 中，确保模块运行正常。 新增用于签名的组建 手工创建或通过命令行创建，sign.component.ts, sign.component.html, sign.component.scss，并且加入到 module.ts 新增配套 service 处理 页面点击触发签名框弹出，保存签名图片到数据库的请求。 后端图片处理 后端需要将前端提交的数据保存到数据库，还需要将数据展现在前端页面。 代码示例 TS 文件 import { Component, Inject, OnInit, SkipSelf, ViewChild } from '@angular/core'; import { ErrorStateMatcher } from '@angular/material/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms'; import { ReportService } from '@core/http/report.service'; import { Report, ReportFill } from '@shared/models/report.models'; import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; import { SignaturePad } from 'angular2-signaturepad'; export interface ReportSignObservationDialogData { report: Report; } @Component({ selector: 'tb-report-sign-observation-dialog', templateUrl: './sign-report-observation-dialog.component.html', styleUrls: ['./sign-report-observation-dialog.component.scss'], providers: [{provide: ErrorStateMatcher, useExisting: ReportSignObservationDialogComponent}] }) export class ReportSignObservationDialogComponent extends DialogComponent<ReportSignObservationDialogComponent, Report> implements OnInit, ErrorStateMatcher { @ViewChild(SignaturePad) signaturePad: SignaturePad; private signaturePadOptions: Object = { // passed through to szimek/signature_pad constructor 'minWidth': 2, 'canvasWidth': 400, // 弹出的窗口宽度 'canvasHeight': 200, // 弹出的窗口高度 'backgroundColor': 'rgb(240,240,240)' // 背景颜色 }; reportSignFormGroup: FormGroup; isReadOnly: boolean; reportSign: String; report: Report; submitted = false; constructor(protected store: Store<AppState>, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: ReportSignObservationDialogData, private reportService: ReportService, @SkipSelf() private errorStateMatcher: ErrorStateMatcher, public dialogRef: MatDialogRef<ReportSignObservationDialogComponent, Report>, public fb: FormBuilder) { super(store, router, dialogRef); } ngAfterViewInit() { // this.signaturePad is now available this.signaturePad.set('minWidth', 2); // set szimek/signature_pad options at runtime this.signaturePad.clear(); // invoke functions from szimek/signature_pad API } signatureImage; drawComplete() { // will be notified of szimek/signature_pad's onEnd event // console.log(this.signaturePad.toDataURL()); this.reportSign = this.signaturePad.toDataURL(); this.signatureImage=this.signaturePad.toDataURL(); // 将图片转换成 base64 码 } drawStart() { // will be notified of szimek/signature_pad's onBegin event // console.log('begin drawing'); } ngOnInit(): void { this.buildReportSign(); this.loadReportSign(); } isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { const originalErrorState = this.errorStateMatcher.isErrorState(control, form); const customErrorState = !!(control && control.invalid && this.submitted); return originalErrorState || customErrorState; } buildReportSign() { this.reportSignFormGroup = this.fb.group({ file: '' }); } loadReportSign() { this.reportSignFormGroup = this.fb.group({ file: '' }); } cancel(): void { this.dialogRef.close(null); } save(): void { this.submitted = true; // console.log(this.data.report.id, this.reportSign); this.report = this.data.report; this.reportService.signReport(this.report, encodeURIComponent(this.reportSign.toString())).subscribe( // 调用保存签名的 service (report) => { this.dialogRef.close(this.report); } ); } } HTML 文件 <mat-toolbar color="primary"> report.sign-report <mat-icon class="material-icons">close</mat-icon> </mat-toolbar> <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> </mat-progress-bar> <signature-pad [options]="signaturePadOptions" (onBeginEvent)="drawStart()" (onEndEvent)="drawComplete()"></signature-pad> {{ 'action.save' | translate }} {{ (isReadOnly ? 'action.close' : 'action.cancel') | translate }} 结果展示 签名提示： 报告结果：
如何在 Kubernetes 中部署 ThingsBoard？步骤很简单，过程很艰辛！
目录 关注我们 关注 ThingsBoard 微信公众号 访问 ThingsBoard 中文社区网站 众所周知，Kubernetes（k8s）太火了，太牛了，咱们把部署在 ThingsBoard 上更是理所当然。一句话总结：步骤很简单，过程很艰辛！ 准备 Docker 和 Kubernetes 环境 安装 Docker Desktop CE 版本 安装 Kubenetes 本地版本 kubectl version --client !/bin/bash get images show images !/bin/bash get images (ui) show images kubectl version kubectl apply -f k8s-dashboard.yaml kubectl proxy kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.41.2/deploy/static/provider/cloud/deploy.yaml kubectl apply -f ingress-nginx.yaml docker pull k8s.gcr.io/ingress-nginx/controller:v0.41.2@sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --watch 关注我们 关注 ThingsBoard 微信公众号 手动增加微信公众号：thingsboard_cn 访问 ThingsBoard 中文社区网站 访问网址：http://www.thingsboard.club 众所周知，Kubernetes（k8s）太火了，太牛了，咱们把部署在 ThingsBoard 上更是理所当然。一句话总结：步骤很简单，过程很艰辛！ 准备 Docker 和 Kubernetes 环境 安装 Docker Desktop CE 版本 笔者使用的老版本 MacBook Pro 13，下载安装 Docker Desktop CE 版本，这个比较简单，官方下载，安装即可完成，启动。 ![docker.png][1] 启用 Docker Desktop 中 Kubernetes ![kubernetes-in-docker.png][2] 哇塞，是不是太简单了？当然不会那么容易搞定，你会一直出现 “Starting” 的状态，别傻等，要去 Google 一下。关键字：如何成功启动 Docker 自带的 Kubernetes？ 总之，你一定要找到办法解决你的 Kubernetes 成功启动。 安装 Kubenetes 本地版本 安装 Kubernetes，就是简单，本地安装搞定 # brew install kubernetes-cli kubectl version --client Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.4", GitCommit:"d360454c9bcd1634cf4cc52d1867af5491dc9c5f", GitTreeState:"clean", BuildDate:"2020-11-12T01:09:16Z", GoVersion:"go1.15.4", Compiler:"gc", Platform:"darwin/amd64"} - 为了让 Docker Desktop 启动 k8s，需下载相关的 docker images，需要通过一个脚本 docker-images-k8s.sh，然后运行，从 aliyun 下载 docker image 比较快。 !/bin/bash set -e KUBE_VERSION=v1.19.3 KUBE_PAUSE_VERSION=3.2 ETCD_VERSION=3.4.13-0 COREDNS_VERSION=1.7.0 GCR_URL=k8s.gcr.io ALIYUN_URL=registry.cn-hangzhou.aliyuncs.com/google_containers get images images=(kube-proxy:${KUBE_VERSION} kube-scheduler:${KUBE_VERSION} kube-controller-manager:${KUBE_VERSION} kube-apiserver:${KUBE_VERSION} pause:${KUBE_PAUSE_VERSION} etcd:${ETCD_VERSION} coredns:${COREDNS_VERSION}) for imageName in ${images[@]} ; do docker pull $ALIYUN_URL/$imageName docker tag $ALIYUN_URL/$imageName $GCR_URL/$imageName docker rmi $ALIYUN_URL/$imageName done show images docker images - 为了查看 k8s 运行状态，web 管理工具 kubernetes dashboard 自然少不了，新建 docker-images-dashboard.sh，运行 !/bin/bash set -e KUBE_DASHBOARD_VERSION=v2.0.3 METRICS_SCRAPER=v1.0.4 KUBENETESUI_URL=kubernetesui ALIYUN_KUBENETESUI_URL=registry.cn-hangzhou.aliyuncs.com/kubernetes_ns get images (ui) imagesui=(dashboard:${KUBE_DASHBOARD_VERSION} metrics-scraper:${METRICS_SCRAPER}) for imageName in ${imagesui[@]} ; do docker pull $ALIYUN_KUBENETESUI_URL/$imageName docker tag $ALIYUN_KUBENETESUI_URL/$imageName $KUBENETESUI_URL/$imageName docker rmi $ALIYUN_KUBENETESUI_URL/$imageName done show images docker images - 再去看 Docker Desktop 中已经启动 k8s了，耐心一点，这个时间比较长，验证一下，发现 Server Version 出现了证明服务器安装成功，且客户端可以连接上 kubectl version Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.4", GitCommit:"d360454c9bcd1634cf4cc52d1867af5491dc9c5f", GitTreeState:"clean", BuildDate:"2020-11-12T01:09:16Z", GoVersion:"go1.15.4", Compiler:"gc", Platform:"darwin/amd64"} Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:41:49Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"linux/amd64"} - 启用 k8s dashboard，需要调用一个 yaml [k8s-dashboard.yaml][3] kubectl apply -f k8s-dashboard.yaml namespace/kubernetes-dashboard created serviceaccount/kubernetes-dashboard created service/kubernetes-dashboard created secret/kubernetes-dashboard-certs created secret/kubernetes-dashboard-csrf created secret/kubernetes-dashboard-key-holder created configmap/kubernetes-dashboard-settings created role.rbac.authorization.k8s.io/kubernetes-dashboard created clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created deployment.apps/kubernetes-dashboard created service/dashboard-metrics-scraper created deployment.apps/dashboard-metrics-scraper created kubectl proxy Starting to serve on 127.0.0.1:8001 - 启动成功后，打开浏览器，就可以登陆 Dashboard 要么证书登陆，要么 token 登陆，先执行： TOKEN=$(kubectl -n kube-system describe secret default| awk '$1=="token:"{print $2}') kubectl config set-credentials docker-desktop --token="${TOKEN}" echo $TOKEN 显示的内容就是 token 1. 证书登陆时，选择 ～/.kube/config 2. token 登陆就是上面那串 ![k8s-dashbaord.png][4] 登陆成功后 ![k8s-dashbaord-home.png][5] # 安装 ThingsBoard 到 k8s ## 安装 ThingsBoard > 根据官方文档，照着执行就好：https://github.com/thingsboard/thingsboard/tree/master/k8s - 保证网络畅通，因为需要从 docker hub 下载 images，建议用国内的镜像地址 - 过程比较麻烦，不好监控，只能不停的刷 docker images 命令查看是不是把镜像拉下来了 REPOSITORY TAG IMAGE ID CREATED SIZE zookeeper 3.5 ce6733a90146 3 days ago 245MB postgres 12 386fd8c60839 3 days ago 314MB k8s.gcr.io/ingress-nginx/controller 81d7cdfa4169 9 days ago 280MB jettech/kube-webhook-certgen v1.5.0 344297e197b6 3 weeks ago 44.7MB docker/desktop-kubernetes kubernetes-v1.19.3-cni-v0.8.5-critools-v1.17.0 7f85afe431d8 5 weeks ago 285MB k8s.gcr.io/kube-proxy v1.19.3 cdef7632a242 5 weeks ago 118MB k8s.gcr.io/kube-apiserver v1.19.3 a301be0cd44b 5 weeks ago 119MB k8s.gcr.io/kube-scheduler v1.19.3 aaefbfa906bd 5 weeks ago 45.7MB k8s.gcr.io/kube-controller-manager v1.19.3 9b60aca1d818 5 weeks ago 111MB thingsboard/tb-coap-transport latest 5635dd5c4fe6 2 months ago 865MB thingsboard/tb-http-transport latest 7f60b6a3bd83 2 months ago 864MB thingsboard/tb-mqtt-transport latest 8dfe9a5bc20d 2 months ago 864MB thingsboard/tb-node latest a66803235c46 2 months ago 1.09GB thingsboard/tb-web-ui latest e215f4aa841a 2 months ago 426MB thingsboard/tb-js-executor latest 7c4fdfa00e27 2 months ago 494MB k8s.gcr.io/etcd 3.4.13-0 0369cf4303ff 2 months ago 253MB kubernetesui/dashboard v2.0.3 503bc4b7440b 5 months ago 225MB k8s.gcr.io/coredns 1.7.0 bfe3a36ebd25 5 months ago 45.2MB redis 4.0 191c4017dcdd 7 months ago 89.3MB kubernetesui/metrics-scraper v1.0.4 86262685d9ab 8 months ago 36.9MB docker/desktop-storage-provisioner v1.1 e704287ce753 8 months ago 41.8MB docker/desktop-vpnkit-controller v1.0 79da37e5a3aa 8 months ago 36.6MB k8s.gcr.io/pause 3.2 80d28bedfe5d 9 months ago 683kB wurstmeister/kafka 2.12-2.2.1 86a9c7e5fd97 11 months ago 422MB - 过了很长一段时间，有可能几个小时后，你查看 docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a9d8b9a28efc e704287ce753 "/storage-provisione…" 6 minutes ago Up 6 minutes k8s_storage-provisioner_storage-provisioner_kube-system_50005a87-62d2-45a0-a39e-c34af43d24c9_3 83e1a62bb612 aaefbfa906bd "kube-scheduler --au…" 6 minutes ago Up 6 minutes k8s_kube-scheduler_kube-scheduler-docker-desktop_kube-system_ee4c94eb845abf1878fb3c4c489b1365_7 b4e4d52ae0bc thingsboard/tb-node "start-tb-node.sh" 7 hours ago Up 7 hours k8s_server_tb-node-5b47bb8bd6-x8g8b_thingsboard_532519fd-7441-4a10-a0b3-3458bb9784a3_5 462b9a657c4f thingsboard/tb-node "start-tb-node.sh" 7 hours ago Up 7 hours k8s_server_tb-node-5b47bb8bd6-vqrvb_thingsboard_3f25d857-1624-4d27-90a5-2c54c35747ee_5 4f3a74233acd thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-vvb9v_thingsboard_46063547-8f06-4e81-85b4-00cb4b2a5f42_7 211329243cdd thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-l5gmw_thingsboard_29f294c1-5fd0-44a5-98a0-3880b6fe7126_7 3a6f946e86be thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-h8zqk_thingsboard_82bc9e2b-5db7-409a-9be5-4e7c21f481b8_6 28085da4bbae thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-ftwf8_thingsboard_0c3f60a2-fd08-4951-9d98-80d08bfa439c_6 ed33cf23175c thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-h2vkl_thingsboard_990be16d-12d8-4f7d-8ce4-1ef4a83ac31b_7 6b7fc0bd2fbb thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-pwc4z_thingsboard_28c0106c-9587-466f-90b3-b3af6eaed7ea_7 520ed4711677 thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-gvx2g_thingsboard_afeb8b5c-ab53-48ba-927f-2d20b5fc6c3b_6 5baeda96c4a3 thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-2z89t_thingsboard_d7ec851c-8648-465a-a855-0a23575e3c3b_6 81f692bc2768 thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-7rl82_thingsboard_08864e79-2af0-42b5-b592-4c1a2db1d5cd_6 cb8bf860467a thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-ljwz8_thingsboard_92de7aab-fca3-4e0c-ac3e-02213603d359_7 917ba1ee6732 thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-c27qd_thingsboard_0c79ed1e-1d65-4d46-a7b1-08de77402549_6 0ada7d6b48b9 thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-k4ncf_thingsboard_cdd283fc-d0a2-45b6-b533-00dd4d38e782_7 ffc91b31b24c thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-5p9tg_thingsboard_87e80c57-0f84-43eb-bf24-13cc309e4cec_7 13b6d7dfb387 thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-zvgrp_thingsboard_1fad5bb8-5793-48e7-8dcc-7cbaf0475192_6 0f63ffec3cbb thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-fvvrx_thingsboard_88c65221-c5d3-419d-a155-21cfee3b7157_7 29c432f70609 thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-zvd2t_thingsboard_e0315452-8b8f-4c0a-9488-d56e296ec962_7 58a2f29e2f6a thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-gpndh_thingsboard_99c29bd4-cb0f-4fb8-8061-ebdda21359de_7 637a32ae8d4d thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-r2r5b_thingsboard_6ba2cc34-d6bb-4c14-96c8-0c11e20fd051_7 0d49592908fd thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-j756s_thingsboard_0be1997a-4d1b-4d01-a3ab-55d6e468f39d_7 5e342a30e5c6 thingsboard/tb-js-executor "start-js-executor.sh" 7 hours ago Up 7 hours k8s_server_tb-js-executor-56bbb8f446-9mmf2_thingsboard_97fc3fa7-ad20-4ffc-a34a-cda7aba93305_7 044277041f7a thingsboard/tb-mqtt-transport "start-tb-mqtt-trans…" 7 hours ago Up 7 hours k8s_server_tb-mqtt-transport-fb5f5d5cd-xkwcn_thingsboard_d91bc9c9-de41-4866-8fe1-03831af3a58c_3 e7b427121ff2 thingsboard/tb-http-transport "start-tb-http-trans…" 7 hours ago Up 7 hours k8s_server_tb-http-transport-64f6f66bc7-zzvqb_thingsboard_520ed11c-239e-4083-919b-fec38277f233_3 a2a4da430f0d thingsboard/tb-http-transport "start-tb-http-trans…" 7 hours ago Up 7 hours k8s_server_tb-http-transport-64f6f66bc7-ztmng_thingsboard_0e628481-0398-4ddd-ad97-31c5987796f9_3 2749cf276c80 wurstmeister/kafka "start-kafka.sh" 7 hours ago Up 7 hours k8s_server_tb-kafka-78957b6557-fc8js_thingsboard_2a3d3e60-0b40-45ba-91da-70f29f270a04_5 f296ce350482 thingsboard/tb-mqtt-transport "start-tb-mqtt-trans…" 7 hours ago Up 7 hours k8s_server_tb-mqtt-transport-fb5f5d5cd-bs4tw_thingsboard_ef25b3b1-658e-4e4c-bd1c-a0ca2ab20ce4_3 d7ebb30d2fc7 postgres "docker-entrypoint.s…" 7 hours ago Up 7 hours k8s_postgres_postgres-5cf775766f-clf89_thingsboard_599ecf9f-068c-416e-ab73-95760f1099db_1 2ad0a6662ca9 thingsboard/tb-coap-transport "start-tb-coap-trans…" 7 hours ago Up 7 hours k8s_server_tb-coap-transport-59cc8bd7bc-82zfk_thingsboard_73404a55-e170-4441-b733-5417db6461ad_1 33c4da97f3d7 thingsboard/tb-coap-transport "start-tb-coap-trans…" 7 hours ago Up 7 hours k8s_server_tb-coap-transport-59cc8bd7bc-g8jdw_thingsboard_a48518d7-c929-4a1f-bcc8-c16fdf903fbf_1 3f8d5b8e9d9f thingsboard/tb-web-ui "start-web-ui.sh" 7 hours ago Up 7 hours k8s_server_tb-web-ui-5958f67cc-lg974_thingsboard_5de819ae-f832-4ab6-bdce-0f29daf037ff_1 beb462957a30 redis "docker-entrypoint.s…" 7 hours ago Up 7 hours k8s_server_tb-redis-7fb674db9-pzndj_thingsboard_6ff6ba21-933d-4366-89eb-3d815f5282c9_1 e24d2ea2e00a thingsboard/tb-web-ui "start-web-ui.sh" 7 hours ago Up 7 hours k8s_server_tb-web-ui-5958f67cc-4k4cj_thingsboard_6f3795e9-ded9-46b8-8067-b4afd63f2571_1 c2161ce93009 zookeeper "/docker-entrypoint.…" 7 hours ago Up 7 hours k8s_server_zookeeper-547c6ffb99-bq42m_thingsboard_11a1e06d-bbf1-4b55-bab5-7d4e4b876f20_1 4e02d9bde8ab 79da37e5a3aa "/kube-vpnkit-forwar…" 7 hours ago Up 7 hours k8s_vpnkit-controller_vpnkit-controller_kube-system_6fa3177c-f779-414d-8acb-1342dd87849b_1 30f7af7ffa00 kubernetesui/dashboard "/dashboard --insecu…" 7 hours ago Up 7 hours k8s_kubernetes-dashboard_kubernetes-dashboard-5dbf55bd9d-bcc2v_kubernetes-dashboard_1e414605-d8c1-4918-8e9b-18bc2c01efe6_1 517bc1b7ac3e 81d7cdfa4169 "/usr/bin/dumb-init …" 7 hours ago Up 7 hours k8s_controller_ingress-nginx-controller-c4f944d4d-wcqxv_ingress-nginx_329aa6a7-2ee5-4747-b77d-82182d9a872f_1 d674f87354ca 86262685d9ab "/metrics-sidecar" 7 hours ago Up 7 hours k8s_dashboard-metrics-scraper_dashboard-metrics-scraper-7b59f7d4df-5dkwl_kubernetes-dashboard_3235eff1-3822-4138-8d0e-d45de95d3cbf_1 faf05611eaa3 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-gvx2g_thingsboard_afeb8b5c-ab53-48ba-927f-2d20b5fc6c3b_1 1a1956a65635 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-coap-transport-59cc8bd7bc-82zfk_thingsboard_73404a55-e170-4441-b733-5417db6461ad_1 d5a382ca986e k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-pwc4z_thingsboard_28c0106c-9587-466f-90b3-b3af6eaed7ea_1 c80049396050 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-kafka-78957b6557-fc8js_thingsboard_2a3d3e60-0b40-45ba-91da-70f29f270a04_1 7b192ede32e5 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-coap-transport-59cc8bd7bc-g8jdw_thingsboard_a48518d7-c929-4a1f-bcc8-c16fdf903fbf_1 c33e9576e5a9 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-http-transport-64f6f66bc7-zzvqb_thingsboard_520ed11c-239e-4083-919b-fec38277f233_1 6e90c5e851b7 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-h2vkl_thingsboard_990be16d-12d8-4f7d-8ce4-1ef4a83ac31b_1 e74011796607 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-ftwf8_thingsboard_0c3f60a2-fd08-4951-9d98-80d08bfa439c_1 8e7b08eaf0e4 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-7rl82_thingsboard_08864e79-2af0-42b5-b592-4c1a2db1d5cd_1 fd3c552a04ee k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-vvb9v_thingsboard_46063547-8f06-4e81-85b4-00cb4b2a5f42_1 d3dc754a1f71 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-l5gmw_thingsboard_29f294c1-5fd0-44a5-98a0-3880b6fe7126_1 372fd6514108 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-gpndh_thingsboard_99c29bd4-cb0f-4fb8-8061-ebdda21359de_1 caf096a5bf42 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-node-5b47bb8bd6-x8g8b_thingsboard_532519fd-7441-4a10-a0b3-3458bb9784a3_1 a80bbd2267ec bfe3a36ebd25 "/coredns -conf /etc…" 7 hours ago Up 7 hours k8s_coredns_coredns-f9fd979d6-ff45j_kube-system_df1c5b8b-26f5-48cc-a853-c050090e69ef_1 1f1b01587d81 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-redis-7fb674db9-pzndj_thingsboard_6ff6ba21-933d-4366-89eb-3d815f5282c9_1 992b5afa6aa1 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-web-ui-5958f67cc-lg974_thingsboard_5de819ae-f832-4ab6-bdce-0f29daf037ff_1 271ad2fced2b k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-fvvrx_thingsboard_88c65221-c5d3-419d-a155-21cfee3b7157_1 344ddec06f1e k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-h8zqk_thingsboard_82bc9e2b-5db7-409a-9be5-4e7c21f481b8_1 6ad3af03d452 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_vpnkit-controller_kube-system_6fa3177c-f779-414d-8acb-1342dd87849b_1 413d3e3fef5f k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-http-transport-64f6f66bc7-ztmng_thingsboard_0e628481-0398-4ddd-ad97-31c5987796f9_1 b42279032251 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-zvd2t_thingsboard_e0315452-8b8f-4c0a-9488-d56e296ec962_1 472cd017176e bfe3a36ebd25 "/coredns -conf /etc…" 7 hours ago Up 7 hours k8s_coredns_coredns-f9fd979d6-k54r2_kube-system_9355c0e5-b8fc-4c3c-9644-89749adeee97_1 3e0fe843bcbe k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_postgres-5cf775766f-clf89_thingsboard_599ecf9f-068c-416e-ab73-95760f1099db_1 e199dac37dec k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-mqtt-transport-fb5f5d5cd-xkwcn_thingsboard_d91bc9c9-de41-4866-8fe1-03831af3a58c_1 e72505d9d064 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-ljwz8_thingsboard_92de7aab-fca3-4e0c-ac3e-02213603d359_1 43362e2031d8 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-2z89t_thingsboard_d7ec851c-8648-465a-a855-0a23575e3c3b_1 9c876bbc23be k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-c27qd_thingsboard_0c79ed1e-1d65-4d46-a7b1-08de77402549_1 11b89fccd02d k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-node-5b47bb8bd6-vqrvb_thingsboard_3f25d857-1624-4d27-90a5-2c54c35747ee_1 9a047136e01b k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-k4ncf_thingsboard_cdd283fc-d0a2-45b6-b533-00dd4d38e782_1 c13f8513edf1 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-zvgrp_thingsboard_1fad5bb8-5793-48e7-8dcc-7cbaf0475192_1 0fada7a20fe0 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-j756s_thingsboard_0be1997a-4d1b-4d01-a3ab-55d6e468f39d_1 3e8bd573933b k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-5p9tg_thingsboard_87e80c57-0f84-43eb-bf24-13cc309e4cec_1 936695bf38e1 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-web-ui-5958f67cc-4k4cj_thingsboard_6f3795e9-ded9-46b8-8067-b4afd63f2571_1 15bc2206a101 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_ingress-nginx-controller-c4f944d4d-wcqxv_ingress-nginx_329aa6a7-2ee5-4747-b77d-82182d9a872f_1 9fb9bcc3f42e k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-mqtt-transport-fb5f5d5cd-bs4tw_thingsboard_ef25b3b1-658e-4e4c-bd1c-a0ca2ab20ce4_1 e5ff72d6497d cdef7632a242 "/usr/local/bin/kube…" 7 hours ago Up 7 hours k8s_kube-proxy_kube-proxy-4fx4m_kube-system_61c86591-198c-4bcc-ac9a-756ba949c71c_1 e8b88981ec37 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_zookeeper-547c6ffb99-bq42m_thingsboard_11a1e06d-bbf1-4b55-bab5-7d4e4b876f20_1 2366f0c673fc k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-r2r5b_thingsboard_6ba2cc34-d6bb-4c14-96c8-0c11e20fd051_1 dc3c77cd895b k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_tb-js-executor-56bbb8f446-9mmf2_thingsboard_97fc3fa7-ad20-4ffc-a34a-cda7aba93305_1 7cef6c1b6fd8 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_coredns-f9fd979d6-ff45j_kube-system_df1c5b8b-26f5-48cc-a853-c050090e69ef_1 7f3bf1c89eef k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_dashboard-metrics-scraper-7b59f7d4df-5dkwl_kubernetes-dashboard_3235eff1-3822-4138-8d0e-d45de95d3cbf_1 cedd269cda38 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_coredns-f9fd979d6-k54r2_kube-system_9355c0e5-b8fc-4c3c-9644-89749adeee97_1 1ff5b8974607 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_kubernetes-dashboard-5dbf55bd9d-bcc2v_kubernetes-dashboard_1e414605-d8c1-4918-8e9b-18bc2c01efe6_1 38c2265588a8 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_storage-provisioner_kube-system_50005a87-62d2-45a0-a39e-c34af43d24c9_1 47dfcf754624 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_kube-proxy-4fx4m_kube-system_61c86591-198c-4bcc-ac9a-756ba949c71c_1 2410f48b0dcb 0369cf4303ff "etcd --advertise-cl…" 7 hours ago Up 7 hours k8s_etcd_etcd-docker-desktop_kube-system_c7cc6a3c3118f127f5fd469ef69477e0_1 8282e8feb792 a301be0cd44b "kube-apiserver --ad…" 7 hours ago Up 7 hours k8s_kube-apiserver_kube-apiserver-docker-desktop_kube-system_2085f5be68201a12aeffb940f7ba4272_1 a8d6bd3cc82a 9b60aca1d818 "kube-controller-man…" 7 hours ago Up 7 hours k8s_kube-controller-manager_kube-controller-manager-docker-desktop_kube-system_07d42b7bf3823b30f57219558fcb55e2_1 acebbb6ddd18 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_kube-scheduler-docker-desktop_kube-system_ee4c94eb845abf1878fb3c4c489b1365_1 d395721ce499 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_kube-controller-manager-docker-desktop_kube-system_07d42b7bf3823b30f57219558fcb55e2_1 ff1cfd6ae1b2 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_kube-apiserver-docker-desktop_kube-system_2085f5be68201a12aeffb940f7ba4272_1 2060020e4bc4 k8s.gcr.io/pause:3.2 "/pause" 7 hours ago Up 7 hours k8s_POD_etcd-docker-desktop_kube-system_c7cc6a3c3118f127f5fd469ef69477e0_1 好多个 container 在跑，好壮观 > 这时，你以为可以成功访问 ThingsBoard 主页吗？不行，真的不行，因为还差一个步骤，非常重要，那就是你的机器还没有 ingress ，建议你去好好读一读这个知识点。 ## 安装 Ingress Nginx - 直接去官方网站看文档，照着执行，但是你需要科学上网：https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.41.2/deploy/static/provider/cloud/deploy.yaml 想办法把这个文件搞下来，因为这是部署 Ingress Nginx 的配置文件 我提供一个备份： [ingress-nginx.yaml][6]，启动： kubectl apply -f ingress-nginx.yaml namespace/ingress-nginx unchanged serviceaccount/ingress-nginx unchanged configmap/ingress-nginx-controller configured clusterrole.rbac.authorization.k8s.io/ingress-nginx unchanged clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx unchanged role.rbac.authorization.k8s.io/ingress-nginx unchanged rolebinding.rbac.authorization.k8s.io/ingress-nginx unchanged service/ingress-nginx-controller-admission unchanged service/ingress-nginx-controller unchanged deployment.apps/ingress-nginx-controller configured validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission configured serviceaccount/ingress-nginx-admission unchanged clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission unchanged clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission unchanged role.rbac.authorization.k8s.io/ingress-nginx-admission unchanged rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission unchanged job.batch/ingress-nginx-admission-create unchanged job.batch/ingress-nginx-admission-patch unchanged - 下载 ingress-nginx 镜像 docker pull k8s.gcr.io/ingress-nginx/controller:v0.41.2@sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de 因为系统提示，这个镜像无法下载，或这很慢，你需要手动执行。看看有没有成功： kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --watch NAME READY STATUS RESTARTS AGE ingress-nginx-admission-create-sd5zj 0/1 Completed 0 16m ingress-nginx-admission-patch-pfjhp 0/1 Completed 2 16m ingress-nginx-controller-c4f944d4d-wcqxv 0/1 Running 0 16m ingress-nginx-controller-c4f944d4d-wcqxv 1/1 Running 0 16m - 查看本地是否已经成功监听 80 和 443 端口，如果存在，那就是跑通了 netstat -na |grep LIST tcp46 0 0 .1883 . LISTEN tcp46 0 0 .443 . LISTEN tcp46 0 0 .80 .* LISTEN - 查看 k8s dashboard 状态 ![tb-in-k8s.png][7] - ThingsBoard 登陆界面，出现太重要了 ![tg-login.png][8] - 成功登陆，且新建租户正常 ![tb-tenant.png][9] ## 最后，不建议在本地跑 k8s，速度太慢了，不如跑 jar 来的方便，调试起来也不方便。开发环境用 mvn spring-boot:run，测试环境直接部署在 CentOS 或 Ubuntu 环境单机跑足够用了，大量数据采集，访问用户数量大，才可以试试 k8s 环境，欢迎大家留言讨论！ ## [1]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/3847183869.png [2]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/1301930728.png [3]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/1712863204.yaml [4]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/15528435.png [5]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/746719120.png [6]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/2160153585.yaml [7]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/1052366375.png [8]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/310291162.png [9]: https://yiqisoft.cn/blogs/usr/uploads/2020/11/2850801996.png
目录 关注我们 关注 ThingsBoard 微信公众号 访问 ThingsBoard 中文社区网站 修改 /usr/share/thingsboard/conf/thingsboard.yml, 将 false 改成 true； 新建 /usr/share/thingsboard/conf/keystore 目录，且此目录下，增加自己的证书 keystore.p12，并授权 thingsboard 用户和组，命令行输入 重启 thingsboard 即可 Chrome 下，无法访问自己制作的证书网站，方法在此 关注我们 关注 ThingsBoard 微信公众号 手动增加微信公众号：thingsboard_cn 访问 ThingsBoard 中文社区网站 访问网址：http://www.thingsboard.club 修改 /usr/share/thingsboard/conf/thingsboard.yml, 将 false 改成 true； # Enable/disable SSL support enabled: "${SSL_ENABLED:true}" 新建 /usr/share/thingsboard/conf/keystore 目录，且此目录下，增加自己的证书 keystore.p12，并授权 thingsboard 用户和组，命令行输入 mkdir /usr/share/thingsboard/conf/keystore keytool -genkey -alias tomcat \ -keystore keystore.p12 \ -storetype PKCS12 \ -keyalg RSA \ -validity 730 \ -keysize 2048 chown -R thingsboard:thingsboard /usr/share/thingsboard/conf/keystore 重启 thingsboard 即可 systemctl restart thingsboard Chrome 下，无法访问自己制作的证书网站，方法在此 关于 Chrome 无法打开自定义的网站证书网站方法