64 changed files with 265 additions and 916 deletions
@ -1,123 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2018 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.system; |
|||
|
|||
import com.fasterxml.jackson.core.type.TypeReference; |
|||
import com.google.common.collect.ImmutableMap; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.controller.AbstractControllerTest; |
|||
|
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
|
|||
public class BaseDeviceOfflineTest extends AbstractControllerTest { |
|||
|
|||
private Device deviceA; |
|||
private Device deviceB; |
|||
private DeviceCredentials credA; |
|||
private DeviceCredentials credB; |
|||
|
|||
@Before |
|||
public void before() throws Exception { |
|||
loginTenantAdmin(); |
|||
deviceA = createDevice("DevA", "VMS"); |
|||
credA = getCredentials(deviceA.getUuidId()); |
|||
deviceB = createDevice("DevB", "SOLAR"); |
|||
credB = getCredentials(deviceB.getUuidId()); |
|||
} |
|||
|
|||
@Test |
|||
public void offlineDevicesCanBeFoundByLastConnectField() throws Exception { |
|||
makeDeviceContact(credA); |
|||
Thread.sleep(1000); |
|||
makeDeviceContact(credB); |
|||
Thread.sleep(100); |
|||
List<Device> devices = doGetTyped("/api/device/offline?contactType=CONNECT&threshold=700", new TypeReference<List<Device>>() { |
|||
}); |
|||
|
|||
assertEquals(devices.toString(),1, devices.size()); |
|||
assertEquals("DevA", devices.get(0).getName()); |
|||
} |
|||
|
|||
@Test |
|||
public void offlineDevicesCanBeFoundByLastUpdateField() throws Exception { |
|||
makeDeviceUpdate(credA); |
|||
Thread.sleep(1000); |
|||
makeDeviceUpdate(credB); |
|||
makeDeviceContact(credA); |
|||
Thread.sleep(100); |
|||
List<Device> devices = doGetTyped("/api/device/offline?contactType=UPLOAD&threshold=700", new TypeReference<List<Device>>() { |
|||
}); |
|||
|
|||
assertEquals(devices.toString(),1, devices.size()); |
|||
assertEquals("DevA", devices.get(0).getName()); |
|||
} |
|||
|
|||
@Test |
|||
public void onlineDevicesCanBeFoundByLastConnectField() throws Exception { |
|||
makeDeviceContact(credB); |
|||
Thread.sleep(1000); |
|||
makeDeviceContact(credA); |
|||
Thread.sleep(100); |
|||
List<Device> devices = doGetTyped("/api/device/online?contactType=CONNECT&threshold=700", new TypeReference<List<Device>>() { |
|||
}); |
|||
|
|||
assertEquals(devices.toString(),1, devices.size()); |
|||
assertEquals("DevA", devices.get(0).getName()); |
|||
} |
|||
|
|||
@Test |
|||
public void onlineDevicesCanBeFoundByLastUpdateField() throws Exception { |
|||
makeDeviceUpdate(credB); |
|||
Thread.sleep(1000); |
|||
makeDeviceUpdate(credA); |
|||
makeDeviceContact(credB); |
|||
Thread.sleep(100); |
|||
List<Device> devices = doGetTyped("/api/device/online?contactType=UPLOAD&threshold=700", new TypeReference<List<Device>>() { |
|||
}); |
|||
|
|||
assertEquals(devices.toString(),1, devices.size()); |
|||
assertEquals("DevA", devices.get(0).getName()); |
|||
} |
|||
|
|||
private Device createDevice(String name, String type) throws Exception { |
|||
Device device = new Device(); |
|||
device.setName(name); |
|||
device.setType(type); |
|||
long currentTime = System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(10); |
|||
device.setLastConnectTs(currentTime); |
|||
device.setLastUpdateTs(currentTime); |
|||
return doPost("/api/device", device, Device.class); |
|||
} |
|||
|
|||
private DeviceCredentials getCredentials(UUID deviceId) throws Exception { |
|||
return doGet("/api/device/" + deviceId.toString() + "/credentials", DeviceCredentials.class); |
|||
} |
|||
|
|||
private void makeDeviceUpdate(DeviceCredentials credentials) throws Exception { |
|||
doPost("/api/v1/" + credentials.getCredentialsId() + "/attributes", ImmutableMap.of("keyA", "valueA"), new String[]{}); |
|||
} |
|||
|
|||
private void makeDeviceContact(DeviceCredentials credentials) throws Exception { |
|||
doGet("/api/v1/" + credentials.getCredentialsId() + "/attributes?clientKeys=keyA,keyB,keyC"); |
|||
} |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2018 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.system.nosql; |
|||
|
|||
import org.thingsboard.server.dao.service.DaoNoSqlTest; |
|||
import org.thingsboard.server.system.BaseDeviceOfflineTest; |
|||
|
|||
@DaoNoSqlTest |
|||
public class DeviceOfflineNoSqlTest extends BaseDeviceOfflineTest { |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2018 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.system.sql; |
|||
|
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
import org.thingsboard.server.system.BaseDeviceOfflineTest; |
|||
|
|||
@DaoSqlTest |
|||
public class DeviceOfflineSqlTest extends BaseDeviceOfflineTest { |
|||
} |
|||
@ -1,40 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2018 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.common.data.device; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Data; |
|||
import lombok.ToString; |
|||
|
|||
@Data |
|||
@AllArgsConstructor |
|||
@ToString |
|||
public class DeviceStatusQuery { |
|||
|
|||
private Status status; |
|||
private ContactType contactType; |
|||
private long threshold; |
|||
|
|||
|
|||
public enum Status { |
|||
ONLINE, OFFLINE |
|||
} |
|||
|
|||
public enum ContactType { |
|||
CONNECT, UPLOAD |
|||
} |
|||
|
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2018 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.device; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.device.DeviceStatusQuery; |
|||
|
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
|
|||
public interface DeviceOfflineService { |
|||
|
|||
void online(Device device, boolean isUpdate); |
|||
|
|||
void offline(Device device); |
|||
|
|||
ListenableFuture<List<Device>> findOfflineDevices(UUID tenantId, DeviceStatusQuery.ContactType contactType, long offlineThreshold); |
|||
|
|||
ListenableFuture<List<Device>> findOnlineDevices(UUID tenantId, DeviceStatusQuery.ContactType contactType, long offlineThreshold); |
|||
} |
|||
@ -1,62 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2018 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.device; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.device.DeviceStatusQuery; |
|||
|
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
|
|||
import static org.thingsboard.server.common.data.device.DeviceStatusQuery.Status.OFFLINE; |
|||
import static org.thingsboard.server.common.data.device.DeviceStatusQuery.Status.ONLINE; |
|||
|
|||
@Service |
|||
public class DeviceOfflineServiceImpl implements DeviceOfflineService { |
|||
|
|||
@Autowired |
|||
private DeviceDao deviceDao; |
|||
|
|||
@Override |
|||
public void online(Device device, boolean isUpdate) { |
|||
long current = System.currentTimeMillis(); |
|||
device.setLastConnectTs(current); |
|||
if(isUpdate) { |
|||
device.setLastUpdateTs(current); |
|||
} |
|||
deviceDao.saveDeviceStatus(device); |
|||
} |
|||
|
|||
@Override |
|||
public void offline(Device device) { |
|||
online(device, false); |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<List<Device>> findOfflineDevices(UUID tenantId, DeviceStatusQuery.ContactType contactType, long offlineThreshold) { |
|||
DeviceStatusQuery statusQuery = new DeviceStatusQuery(OFFLINE, contactType, offlineThreshold); |
|||
return deviceDao.findDevicesByTenantIdAndStatus(tenantId, statusQuery); |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<List<Device>> findOnlineDevices(UUID tenantId, DeviceStatusQuery.ContactType contactType, long offlineThreshold) { |
|||
DeviceStatusQuery statusQuery = new DeviceStatusQuery(ONLINE, contactType, offlineThreshold); |
|||
return deviceDao.findDevicesByTenantIdAndStatus(tenantId, statusQuery); |
|||
} |
|||
} |
|||
@ -1,68 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2018 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.rule.engine.mail; |
|||
|
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import org.apache.velocity.Template; |
|||
import org.apache.velocity.VelocityContext; |
|||
import org.apache.velocity.runtime.RuntimeServices; |
|||
import org.apache.velocity.runtime.RuntimeSingleton; |
|||
import org.apache.velocity.runtime.parser.ParseException; |
|||
import org.apache.velocity.runtime.parser.node.SimpleNode; |
|||
import org.thingsboard.server.common.msg.TbMsg; |
|||
|
|||
import java.io.IOException; |
|||
import java.io.StringReader; |
|||
import java.io.StringWriter; |
|||
import java.util.Map; |
|||
|
|||
import static org.thingsboard.server.common.msg.TbMsgDataType.JSON; |
|||
|
|||
public class RuleVelocityUtils { |
|||
|
|||
public static VelocityContext createContext(TbMsg msg) throws IOException { |
|||
VelocityContext context = new VelocityContext(); |
|||
context.put("originator", msg.getOriginator()); |
|||
context.put("type", msg.getType()); |
|||
context.put("metadata", msg.getMetaData().values()); |
|||
if (msg.getDataType() == JSON) { |
|||
Map map = new ObjectMapper().readValue(msg.getData(), Map.class); |
|||
context.put("msg", map); |
|||
} else { |
|||
context.put("msg", msg.getData()); |
|||
} |
|||
return context; |
|||
} |
|||
|
|||
public static String merge(Template template, VelocityContext context) { |
|||
StringWriter writer = new StringWriter(); |
|||
template.merge(context, writer); |
|||
return writer.toString(); |
|||
} |
|||
|
|||
public static Template create(String source, String templateName) throws ParseException { |
|||
RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices(); |
|||
StringReader reader = new StringReader(source); |
|||
SimpleNode node = runtimeServices.parse(reader, templateName); |
|||
Template template = new Template(); |
|||
template.setRuntimeServices(runtimeServices); |
|||
template.setData(node); |
|||
template.initDocument(); |
|||
return template; |
|||
} |
|||
|
|||
|
|||
} |
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue