23 changed files with 313 additions and 282 deletions
@ -0,0 +1,24 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.exception; |
||||
|
|
||||
|
public class CalculatedFieldStateException extends Exception { |
||||
|
|
||||
|
public CalculatedFieldStateException(String message) { |
||||
|
super(message); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,147 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.utils; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.StringUtils; |
||||
|
import org.thingsboard.server.common.data.cf.CalculatedFieldType; |
||||
|
import org.thingsboard.server.common.data.id.CalculatedFieldId; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
import org.thingsboard.server.common.data.id.EntityIdFactory; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
import org.thingsboard.server.common.data.kv.BasicKvEntry; |
||||
|
import org.thingsboard.server.common.util.KvProtoUtil; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.CalculatedFieldEntityCtxIdProto; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.CalculatedFieldStateProto; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.SingleValueArgumentProto; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.TsRollingArgumentEntryProto; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.TsValueListProto; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.TsValueProto; |
||||
|
import org.thingsboard.server.service.cf.ctx.CalculatedFieldEntityCtxId; |
||||
|
import org.thingsboard.server.service.cf.ctx.state.CalculatedFieldState; |
||||
|
import org.thingsboard.server.service.cf.ctx.state.ScriptCalculatedFieldState; |
||||
|
import org.thingsboard.server.service.cf.ctx.state.SimpleCalculatedFieldState; |
||||
|
import org.thingsboard.server.service.cf.ctx.state.SingleValueArgumentEntry; |
||||
|
import org.thingsboard.server.service.cf.ctx.state.TsRollingArgumentEntry; |
||||
|
|
||||
|
import java.util.Optional; |
||||
|
import java.util.TreeMap; |
||||
|
import java.util.UUID; |
||||
|
|
||||
|
public class CalculatedFieldUtils { |
||||
|
|
||||
|
public static CalculatedFieldEntityCtxIdProto toProto(CalculatedFieldEntityCtxId ctxId) { |
||||
|
return CalculatedFieldEntityCtxIdProto.newBuilder() |
||||
|
.setTenantIdMSB(ctxId.tenantId().getId().getMostSignificantBits()) |
||||
|
.setTenantIdLSB(ctxId.tenantId().getId().getLeastSignificantBits()) |
||||
|
.setCalculatedFieldIdMSB(ctxId.cfId().getId().getMostSignificantBits()) |
||||
|
.setCalculatedFieldIdLSB(ctxId.cfId().getId().getLeastSignificantBits()) |
||||
|
.setEntityType(ctxId.entityId().getEntityType().name()) |
||||
|
.setEntityIdMSB(ctxId.entityId().getId().getMostSignificantBits()) |
||||
|
.setEntityIdLSB(ctxId.entityId().getId().getLeastSignificantBits()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
public static CalculatedFieldEntityCtxId fromProto(CalculatedFieldEntityCtxIdProto ctxIdProto) { |
||||
|
TenantId tenantId = TenantId.fromUUID(new UUID(ctxIdProto.getTenantIdMSB(), ctxIdProto.getTenantIdLSB())); |
||||
|
EntityId entityId = EntityIdFactory.getByTypeAndUuid(ctxIdProto.getEntityType(), new UUID(ctxIdProto.getEntityIdMSB(), ctxIdProto.getEntityIdLSB())); |
||||
|
CalculatedFieldId calculatedFieldId = new CalculatedFieldId(new UUID(ctxIdProto.getCalculatedFieldIdMSB(), ctxIdProto.getCalculatedFieldIdLSB())); |
||||
|
return new CalculatedFieldEntityCtxId(tenantId, calculatedFieldId, entityId); |
||||
|
} |
||||
|
|
||||
|
public static CalculatedFieldStateProto toProto(CalculatedFieldEntityCtxId stateId, CalculatedFieldState state) { |
||||
|
CalculatedFieldStateProto.Builder builder = CalculatedFieldStateProto.newBuilder() |
||||
|
.setId(toProto(stateId)) |
||||
|
.setType(state.getType().name()); |
||||
|
|
||||
|
state.getArguments().forEach((argName, argEntry) -> { |
||||
|
if (argEntry instanceof SingleValueArgumentEntry singleValueArgumentEntry) { |
||||
|
builder.addSingleValueArguments(toSingleValueArgumentProto(argName, singleValueArgumentEntry)); |
||||
|
} else if (argEntry instanceof TsRollingArgumentEntry rollingArgumentEntry) { |
||||
|
builder.addRollingValueArguments(toRollingArgumentProto(argName, rollingArgumentEntry)); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
return builder.build(); |
||||
|
} |
||||
|
|
||||
|
public static SingleValueArgumentProto toSingleValueArgumentProto(String argName, SingleValueArgumentEntry entry) { |
||||
|
SingleValueArgumentProto.Builder builder = SingleValueArgumentProto.newBuilder() |
||||
|
.setArgName(argName); |
||||
|
|
||||
|
if (entry.getKvEntryValue() != null) { |
||||
|
builder.setValue(KvProtoUtil.toTsValueProto(entry.getTs(), entry.getKvEntryValue())); |
||||
|
} |
||||
|
|
||||
|
Optional.ofNullable(entry.getVersion()).ifPresent(builder::setVersion); |
||||
|
|
||||
|
return builder.build(); |
||||
|
} |
||||
|
|
||||
|
public static TsRollingArgumentEntryProto toRollingArgumentProto(String argName, TsRollingArgumentEntry entry) { |
||||
|
TsValueListProto.Builder tsRecordsBuilder = TsValueListProto.newBuilder() |
||||
|
.setKey(argName); |
||||
|
|
||||
|
entry.getTsRecords().forEach((ts, value) -> tsRecordsBuilder.addTsValue(KvProtoUtil.toTsValueProto(ts, value))); |
||||
|
|
||||
|
return TsRollingArgumentEntryProto.newBuilder() |
||||
|
.setLimit(entry.getLimit()) |
||||
|
.setTimeWindow(entry.getTimeWindow()) |
||||
|
.setRecords(tsRecordsBuilder.build()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
public static CalculatedFieldState fromProto(CalculatedFieldStateProto proto) { |
||||
|
if (StringUtils.isEmpty(proto.getType())) { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
CalculatedFieldType type = CalculatedFieldType.valueOf(proto.getType()); |
||||
|
|
||||
|
CalculatedFieldState state = switch (type) { |
||||
|
case SIMPLE -> new SimpleCalculatedFieldState(); |
||||
|
case SCRIPT -> new ScriptCalculatedFieldState(); |
||||
|
}; |
||||
|
|
||||
|
proto.getSingleValueArgumentsList().forEach(argProto -> |
||||
|
state.getArguments().put(argProto.getArgName(), fromSingleValueArgumentProto(argProto))); |
||||
|
|
||||
|
if (CalculatedFieldType.SCRIPT.equals(type)) { |
||||
|
proto.getRollingValueArgumentsList().forEach(argProto -> |
||||
|
state.getArguments().put(argProto.getRecords().getKey(), fromRollingArgumentProto(argProto))); |
||||
|
} |
||||
|
|
||||
|
return state; |
||||
|
} |
||||
|
|
||||
|
public static SingleValueArgumentEntry fromSingleValueArgumentProto(SingleValueArgumentProto proto) { |
||||
|
TsValueProto tsValueProto = proto.getValue(); |
||||
|
long ts = tsValueProto.getTs(); |
||||
|
BasicKvEntry kvEntry = (BasicKvEntry) KvProtoUtil.fromTsValueProto(proto.getArgName(), tsValueProto); |
||||
|
return new SingleValueArgumentEntry(ts, kvEntry, proto.getVersion()); |
||||
|
} |
||||
|
|
||||
|
public static TsRollingArgumentEntry fromRollingArgumentProto(TsRollingArgumentEntryProto proto) { |
||||
|
TsValueListProto records = proto.getRecords(); |
||||
|
String key = records.getKey(); |
||||
|
TreeMap<Long, BasicKvEntry> tsRecords = new TreeMap<>(); |
||||
|
records.getTsValueList().forEach(tsValueProto -> { |
||||
|
BasicKvEntry kvEntry = (BasicKvEntry) KvProtoUtil.fromTsValueProto(key, tsValueProto); |
||||
|
tsRecords.put(tsValueProto.getTs(), kvEntry); |
||||
|
}); |
||||
|
return new TsRollingArgumentEntry(tsRecords, proto.getLimit(), proto.getTimeWindow()); |
||||
|
} |
||||
|
|
||||
|
} |
||||
Loading…
Reference in new issue