npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@tslfe/dt-engine

v4.2.2-6

Published

tacos dt engine

Downloads

1,193

Readme

SDK


安装(windows)

  1. 获取孪生授权服务压缩包,并解压到本地文件夹,文件目录如下:
  jre 运行环境
  tslauthor 授权服务
    logs 运行日志
    static 静态文件,包含模型相关的文件和配置信息
    application.yml 配置文件
    tslenrypt.exe 服务启动
  1. 提供应用信息(应用名称、ip地址、mac地址、开始时间、结束时间),从特斯联获取授权license
  2. 获取加密后的模型,放置 tslauthor/static/encry 文件夹中
  3. 点击运行 tslenrypt.exe
  4. 应用程序使用孪生SDK,连接孪生授权服务地址加载模型
  5. 根据SDK弹出的授权页面(第一次或者license过期),输入license并保存
  6. 结束

与 TacOS 建立连接

import Tacos from "@tslfe/dt-engine";

Tacos.connect({
  host: "",
  appid: "",
  token: ""
}).then((meta) => {
  // 建立连接后可获取 meta 实例对象
});

资源定位符格式说明

相对路径: ./
绝对路径: /
设备类型:device
空间类型:space
模式:mode
规则:regular
计划:scheduler
事件:event
状态:state
管道符: |

示例:
./yingli46/meeting01/[device=Light|Curtain]
./yingli46/[space=Office]
./yingli46/[mode=OnWork]
./yingli46/[regular=XXXX]
./yingli46/[scheduler=XXXX]
./yingli46/[event=XXXX]
./yingli46/[state=XXXX]

getDeivce('./yingli46/[device=Light|Curtain]')
or
// getDevice方法可以省略类型标识符: device
getDeivce('./yingli46/[Light|Curtain]')

getSpace('./yingli46/[Office|MeetingRoom]')
or
// getSpace方法可以省略类型标识符: space
getSpace('./yingli46/[Office|MeetingRoom]')

拓展:
// 获取英利46楼所有楼层的会议室
/yingli/yingli46/[space=MeetingRoom]
// 获取英利50楼所有楼层的会议室
/yingli/yingli50/[space=MeetingRoom]
// 获取英利所有楼层的会议室
/yingli/*/[space=MeetingRoom]

内置的全局特殊资源

环境: /env
时间属性:/env/[state=time]
其它属性:?

功能演示

import { Mode, Event } from '@tslfe/tacos-space'

// 进入指定的空间
await meta.enter('./yingli46')

//=====================1. 设备 分割线 =====================

// 获取当前空间下的所有窗帘
let curtainGroup = await meta.getDevice<"Curtain">('./[device=Curtain]');
------------------------------------------- 增加方位西向筛选控制窗帘
// 批量开窗帘
curtainGroup.open();
// 批量关窗帘
curtainGroup.close();
// 监听设备的事件
curtainGroup.addEventListener('event', (event)=>{
  // 设备离线
  // 设备异常
})
// 监听设备状态变化
let removeListener = curtainGroup.addEventListener('state', (event)=>{
  // 设备状态
})
// 移除设备状态监听器
removeListener();

//=====================2. 模式 分割线 =====================

// 获取当前空间下的所有办公区
let officeGroup = meta.getSpace<"Office">('./[type=Office]');
// 批量切换为上班模式
officeGroup.toggleMode(Mode.Office.OnWork);
// 批量切换为下班模式
officeGroup.toggleMode(Mode.Office.OffWork);

// 从办公区集合中查找指定的某一个办公区
let office = officeGroup.findById('officeId');
// 从当前空间中查找指定的办公区
let office = meta.getSpace('<officeId>');
// 从当前空间中根据资源定位符查询空间
let office = meta.getSpace('/yingli46/bangongqu01');

//=====================3. 计划 分割线 =====================

// 设置当前的日期和时间触发空间计划(见第 7 节测试)
tester.time.set('2022-09-11 09:00:00')

// 创建新的计划
meta.scheduler
  .create('scheduler name')
  .month(6,7,8,9)
  .week(1,2,3,4,5)
  .time(['09:00', '12:00'],['13:30','18:00'])
  .action({
    './[device=AirCondition]': {
      [AirCondition.Property.Status]: 1,
      [AirCondition.Property.Temperature]: 26,
    },
    './[device=Light]': {
      [Light.Property.Status]: 1
    }
  })
  .apply(['/yingli46/[space=Office]', '/yingli46/[space=MeetingRoom]']);

// 获取计划
let scheduler = meta.getSpace('/yingli46/[space=Office]').getScheduler('scheduler name');
// 当前计划应用到其它更多空间
scheduler.apply(['/yingli50/[space=Office]', '/yingli50/[space=MeetingRoom]']);
// 冻结计划
scheduler.disable();
// 启用计划
scheduler.enable();
// 删除计划
scheduler.remove();

//=====================4. 规则 分割线 =====================

// 修改空间属性触发空间规则(见第 7 节测试)
let space = meta.getSpace<"Office">('/yingli46/bangongqu01');
tester.space.set(space, {temperature: 40});
// 简化版本
tester.space.set('/yingli46/bangongqu01', {[Office.Property.Temperature]: 40});

// 创建规则
meta.regular
  .create('Temperature-Exceeded-Threshold-Summer')
  .if({
    and: {
      '/env/[state=time]': '>=09:00 && <=18:00',
      or: {
        './[state=temperature]': '>30',
        './[state=co2]': '>0.05'
      }
    }
  })
  .action({
    './[device=AirCondition]': {
      [AirCondition.Property.Status]: 1,
      [AirCondition.Property.FanFreq]: 1,
      [AirCondition.Property.Mode]: 2
    },
    './[mode=OnWork]': {},
  })
  .apply(['/yingli46/[space=Office]', '/yingli46/[space=MeetingRoom]']);

// 获取规则
let regular =meta.getSpace('/yingli46/[space=Office]').getRegular('regular name');
// 当前规则应用到其它更多空间
regular.apply(['/yingli50/[space=Office]', '/yingli50/[space=MeetingRoom]']);
// 冻结规则
regular.disable();
// 启用规则
regular.enable();
// 删除规则
regular.remove();

//=====================5. 指标 & 看板 分割线 ===============

let office = meta.getSpace('/yingli46/bangongqu01');
// 渲染空间的平均温度指标图表
let chart = office.chart(Chart.Temperature.Average, {
  positoin: [0, 0],
  size: [100, 100],
  horizontal: Board.Align.Left,
  vertical: Board.Align.Top
});
// 渲染
chart.render('el')
// 设置图表位置, eg: x=0, y=0
chart.position(0, 0);
// 重新设置水平、垂直方向都居中(处于屏幕中心位置)
chart.align({
  horizontal: Board.Align.Center,
  vertical: Board.Align.Center
});
// 设置图标大小,eg: 宽100 高150
chart.size(100, 150);
// 移除图表
chart.remove();

// 从当前空间中根据资源定位符查询空间
let office = meta.getSpace('/yingli46/bangongqu01'); --------------------------------------------------- dashboard 左右靠边对齐能否实现 ?
// 渲染办公区舒适度看板
let board = office.board(Board.Office.Comfortable, {
  positoin: [0, 0],
  size: [100, 100],
  horizontal: Board.Align.Left,
  vertical: Board.Align.Top
});
// 渲染
board.render('el');
// 重新设置看板位置, eg: x=0, y=0
board.position(0, 0);
// 重新设置水平、垂直方向都居中(处于屏幕中心位置)
board.align({
  horizontal: Board.Align.Center,
  vertical: Board.Align.Center
});
// 设置看板大小,eg: 宽100 高150
board.size(100, 150);
// 移除看板
board.remove();

//=====================6. 布局(三维) 分割线 =====================

// 获取灯模型
let lightModelGroup = meta.getModel('/yingli/46/device/Light');
// 批量修改灯的透明度为0.5
lightModelGroup.opacity = 0.5;
// 批量修改灯的颜色
lightModelGroup.color = '#ffffff';
// 批量修改灯的位置
lightModelGroup.position = new Vector(0,0,0);
// 批量修改灯的缩放
lightModelGroup.scale = new Vector(0,0,0);
// 旋转
lightModelGroup.rotation = new Vector(0,0,0);

// 从灯组中查找指定ID的灯
let lightModel = lightModelGroup.findById('lightId');
// 镜头飞到 lightModel位置
lightModel.foucs();
// 隐藏 lightModel
lightModel.hide();
// 显示 lightModel
lightModel.show();
// 显示 lightModel 的线框
lightModel.outline();
// 选中 lightModel
lightModel.select();

// 镜头飞到合适的位置观察这一组灯
meta.camera.setAutoRotate(true, 2, lightModelGroup);
// 停止观察
meta.camera.setAutoRotate(false);

// 镜头按照指定的物体顺序进行 travel ----------------------------------------------- 直接用 id 数组
meta.camera.travel([
  meta.getModel('<DoorId>'),
  meta.getModel('<lightId>'),
  meta.getModel('<windowId>'),
  meta.getModel('<windowId>'),
  meta.getModel('./[device=Curtain]')
], {loop: true, speed: Camera.Travel.Slow, mode: 'reverse' | 'loop'});
// 支持直接传ID
meta.camera.travel([
  '<DoorId>',
  '<lightId>',
  '<windowId>',
  '<windowId>'
], {loop: true, speed: Camera.Travel.Slow, mode: 'reverse' | 'loop'});
// 支持通过已经获取到的设备进行travel
let lightGroup = meta.getDevice<"Light">('./[Light]');
meta.camera.travel(lightGroup);
// 缩放
meta.camera.zoom(2)


// 图层过滤:只显示电动窗图层
meta.layer.filter('./[device=Widnow]');
// 清空所有图层
meta.layer.clear();
// 重置图层显示
meta.layer.reset();
// 监听视域发生变化
let closeViewChangeListener = meta.layer.onViewChange((list)=>{
  // 变化后的视域范围内的图层
})
// 关闭视域变化监听
closeViewChangeListener();

// 开启下雨情景
let raining = meta.environment.raining(Environment.Rain.Small);
// 停止下雨
meta.environment.clear(raining);

// 开启下雪情景
let snowing = meta.environment.snowing(Environment.Snowing.Small);
// 停止下雪
meta.environment.clear(snowing);

//=====================7. 测试 分割线 =====================

// 构造测试对象
let tester = meta.genTester(); ---------------------------------------------------- Test 未必来自 Meta
// 另一种实例化方式(需要在重新调动connect方法并设置参数)
let tester = await TacosTester.connect({host: '', token: '', appid: ''});

// 设置当前的日期和时间触发空间计划
tester.time.set('2022-09-11 90:00:00')

// 修改空间属性触发空间规则
let space = meta.getSpace('/yingli46/bangongqu01');
tester.space.set(space, {temperature: 40});
// 简化版本
tester.space.set('/yingli46/bangongqu01', {temperature: 40});

// 触发空间事件
let event = meta.getSpace('/yingli46/bangongqu01').getEvent('eventName')
tester.space.emit(event);
// 简化版本
tester.space.emit('/yingli46/bangongqu01/[event=FireAlarm]');
  1. studio 标注(逃生路线、摄像头的配置、地板、墙)
  2. ai