类 如何在 Samsung SmartThings 应用程序中实现设备和传感器?
How classes for devices and sensors are implemented in Samsung SmartThings applications?
我们想为三星 Groovy SmartThings 实施基础设施。当然,基础设施的主要部分是使用相应的方法为每个设备实现不同的 classes。
例如,对于锁的设备,我们假设我们有一把锁 class,方法是 lock() 和 unlock()。这里的问题是我们在 Groovy:
中的一个 SmartThings 应用程序中有这部分代码
def presence(evt)
{
if (evt.value == "present") {
//Somecode
lock1.unlock()
}
else {
//Somecode
lock1.lock()
}
}
所以很可能,lock1 是 class 锁的对象,而 lock() 和 unlock() 是 class 的方法。事情是这样的:
使用 lock1[0].unlock() 命令解锁编号为 #0 的门锁,但使用 lock1.unlock() 命令解锁所有门锁。
这里的问题是 class 是如何创建的?如果 lock1 是一个对象列表,我们如何才能拥有像 lock1.unlock() 这样的命令。
这里的要点是两个对象都应具有相同的名称 lock1,并且两个方法都是名为 lock() 的相同方法。
提前致谢。
这里有 2 个选项:
1) 使用 Groovy 的扩展运算符对列表的每个元素调用该方法:
List lock1 = [.....]
lock1.*lock()
2) 创建一个 Lock
class 扩展或包含元素列表,并向其添加一个 class-level 方法:
class Lock {
List locks
def lock() {
locks.*lock()
}
// this method allows for calls like lock1[42].lock()
def getAt( int ix ) {
locks[ ix ]
}
}
实际上,继承对于物联网设备来说是不好的。
这里要看到的"problem"是Groovy中的(隐含的)spread operator。
The expression cars*.make
is equivalent to cars.collect{ it.make }
. Groovy’s GPath notation allows a short-cut when the referenced property isn’t a property of the containing list, in that case it is automatically spread. In the previously mentioned case, the expression cars.make
can be used, though retaining the explicit spread-dot operator is often recommended.
(那里的例子说的是 GPath,但对于列表、地图等也是如此)
所以在这种情况下 lock1.unlock()
是 lock1*.unlock()
。 (动态)Groovy 会看到,列表中没有 unlock()
方法,只是散开。
至于"So most probably, lock1 is the object for class lock",会让你做噩梦。不要猜测 - 找出答案。您可以 println(lock1.inspect())
了解详细信息,希望 class 的作者有先见之明来添加有用的 toString()
方法。检查文档,你分配 locks1
的函数 returns 是什么。使用工具,告诉您类型(IDE、调试器、...)。
对于开发者更好的命名有帮助:
// BAD naming
def locks1 = smartThings.getAll(Lock, clientId)
// better naming, add the type if it helps you or your IDE
Collection<Lock> allLocks = smartThings.getAll(Lock, clientId)
现在,如果您调用 allLocks.lock()
,发生的事情就更明显了。
要防止隐式扩展运算符,您可以在 groovy 脚本中使用静态编译。例如:
class Lock {
def lock() { println "lock" }
def unlock() { println "unlock" }
}
@groovy.transform.CompileStatic
class X {
public static main() {
[new Lock()].lock()
}
}
这不会编译:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
x.groovy: 9: [Static type checking] - Cannot find matching method java.util.List#lock(). Please check if the declared type is correct and if the method exists.
@ line 9, column 3.
[new Lock()].lock()
^
1 error
使用显式扩展运算符 ([new Lock()]*.lock()
) 进行编译。
我们想为三星 Groovy SmartThings 实施基础设施。当然,基础设施的主要部分是使用相应的方法为每个设备实现不同的 classes。 例如,对于锁的设备,我们假设我们有一把锁 class,方法是 lock() 和 unlock()。这里的问题是我们在 Groovy:
中的一个 SmartThings 应用程序中有这部分代码def presence(evt)
{
if (evt.value == "present") {
//Somecode
lock1.unlock()
}
else {
//Somecode
lock1.lock()
}
}
所以很可能,lock1 是 class 锁的对象,而 lock() 和 unlock() 是 class 的方法。事情是这样的: 使用 lock1[0].unlock() 命令解锁编号为 #0 的门锁,但使用 lock1.unlock() 命令解锁所有门锁。
这里的问题是 class 是如何创建的?如果 lock1 是一个对象列表,我们如何才能拥有像 lock1.unlock() 这样的命令。
这里的要点是两个对象都应具有相同的名称 lock1,并且两个方法都是名为 lock() 的相同方法。
提前致谢。
这里有 2 个选项:
1) 使用 Groovy 的扩展运算符对列表的每个元素调用该方法:
List lock1 = [.....]
lock1.*lock()
2) 创建一个 Lock
class 扩展或包含元素列表,并向其添加一个 class-level 方法:
class Lock {
List locks
def lock() {
locks.*lock()
}
// this method allows for calls like lock1[42].lock()
def getAt( int ix ) {
locks[ ix ]
}
}
实际上,继承对于物联网设备来说是不好的。
这里要看到的"problem"是Groovy中的(隐含的)spread operator。
The expression
cars*.make
is equivalent tocars.collect{ it.make }
. Groovy’s GPath notation allows a short-cut when the referenced property isn’t a property of the containing list, in that case it is automatically spread. In the previously mentioned case, the expressioncars.make
can be used, though retaining the explicit spread-dot operator is often recommended.
(那里的例子说的是 GPath,但对于列表、地图等也是如此)
所以在这种情况下 lock1.unlock()
是 lock1*.unlock()
。 (动态)Groovy 会看到,列表中没有 unlock()
方法,只是散开。
至于"So most probably, lock1 is the object for class lock",会让你做噩梦。不要猜测 - 找出答案。您可以 println(lock1.inspect())
了解详细信息,希望 class 的作者有先见之明来添加有用的 toString()
方法。检查文档,你分配 locks1
的函数 returns 是什么。使用工具,告诉您类型(IDE、调试器、...)。
对于开发者更好的命名有帮助:
// BAD naming
def locks1 = smartThings.getAll(Lock, clientId)
// better naming, add the type if it helps you or your IDE
Collection<Lock> allLocks = smartThings.getAll(Lock, clientId)
现在,如果您调用 allLocks.lock()
,发生的事情就更明显了。
要防止隐式扩展运算符,您可以在 groovy 脚本中使用静态编译。例如:
class Lock {
def lock() { println "lock" }
def unlock() { println "unlock" }
}
@groovy.transform.CompileStatic
class X {
public static main() {
[new Lock()].lock()
}
}
这不会编译:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
x.groovy: 9: [Static type checking] - Cannot find matching method java.util.List#lock(). Please check if the declared type is correct and if the method exists.
@ line 9, column 3.
[new Lock()].lock()
^
1 error
使用显式扩展运算符 ([new Lock()]*.lock()
) 进行编译。