BaseCommand

本文介绍了一个用于Android应用中串口通信的BaseCommand类。该类实现了序列化接口,并提供了构造函数、getter和setter方法来处理头部、ID、数据、CRC校验等功能。此外,还介绍了如何计算命令大小及CRC值。

 

import java.io.Serializable;

import android.util.Log;

public class BaseCommand implements Serializable {

/**
*
*/
private static final long serialVersionUID = 2677660408587776109L;

private String head;
private String id;
private String size;
private String data;
private String crc;

public BaseCommand() {

}

public BaseCommand(String head, String id, String data) {
this.head = head;
this.id = id;
this.data = data;
/*if (null != this.head && null != this.id && null != this.data) {
this.size = CommandHelper.intToHexString(head.length() / 2
+ id.length() / 2 + data.length() / 2 + 2);
Log.d("SerialPort", "size = " + size);
}*/
}

public String getHead() {
return this.head;
}

public void setHead(String head) {
this.head = head;
}

public String getId() {
return this.id;
}

public void setId(String id) {
this.id = id;
}

public String getCrc() {
if(null != crc){
return crc;
} else {
return "";
}
}

public void setCrc(String crc){
this.crc = crc;
}

public String getCommand() {
if (null != this.head && null != this.id && null != this.data) {
String result = head + id;
if(null != size){
result = result + size;
}
result = result + data;
if(null != crc){
result = result + crc;
}
return result;
} else {
return "";
}
}

/*
* public String getSize(){ return this.size; }
*
* public void setSize(String size){ this.size = size; }
*/

public String getData() {
return this.data;
}

public void setData(String data) {
this.data = data;
if (null != this.head && null != this.id && null != this.data) {
/*this.size = CommandHelper.intToHexString(head.length() / 2
+ id.length() / 2 + data.length() / 2 + 2);
Log.d("SerialPort", "size = " + size);*/
}
}

public void caculateSize(){
if (null != this.head && null != this.id && null != this.data) {
this.size = CommandHelper.intToHexString(head.length() / 2
+ id.length() / 2 + data.length() / 2 + 2);
Log.d("SerialPort", "size = " + size);
}
}

public boolean caculateCrc() {
if (null == this.head || null == this.id
|| null == this.data || (data.length() % 2 != 0)) {
Log.d("SerialPort", "content null");
return false;
}
this.crc = CommandHelper.crcValue(head, id, size, data);
if (null != this.crc) {
Log.d("SerialPort", "crc is not null");
return true;
} else {
Log.d("SerialPort", "crc is null");
return false;
}

}
}

转载于:https://www.cnblogs.com/gtgl/p/4685126.html

请帮我改造成使用Processor的: @Slf4j @Component public class ScheduledTaskHandler implements TransformerSupplier<String, ScheduledTaskEvent, KeyValue<String, ScheduledTaskEvent>> { private final TaskHandlerRegistry handlerRegistry; private final Gson gson; private static final String STORE_NAME = "SCHEDULED-TASK-STORE"; public ScheduledTaskHandler(TaskHandlerRegistry handlerRegistry, Gson gson) { this.handlerRegistry = handlerRegistry; this.gson = gson; } @Override public Transformer<String, ScheduledTaskEvent, KeyValue<String, ScheduledTaskEvent>> get() { return new ScheduledTaskTransformer(handlerRegistry, gson); } @Override public Set<StoreBuilder<?>> stores() { return Set.of(Stores.keyValueStoreBuilder( Stores.persistentKeyValueStore(STORE_NAME), Serdes.String(), new JsonSerde<>(ScheduledTaskEvent.class) )); } static class ScheduledTaskTransformer implements Transformer<String, ScheduledTaskEvent, KeyValue<String, ScheduledTaskEvent>> { private final TaskHandlerRegistry handlerRegistry; private final Gson gson; private ProcessorContext context; private KeyValueStore<String, ScheduledTaskEvent> taskStore; private final ConcurrentMap<String, Cancellable> cancellableMap = new ConcurrentHashMap<>(); private final PriorityQueue<ScheduledTaskEvent> pendingTasks = new PriorityQueue<>(Comparator.comparingLong(ScheduledTaskEvent::scheduledTime)); public ScheduledTaskTransformer(TaskHandlerRegistry handlerRegistry, Gson gson) { this.handlerRegistry = handlerRegistry; this.gson = gson; } @Override public void init(ProcessorContext context) { this.context = context; this.taskStore = context.getStateStore(STORE_NAME); // Recover pending tasks from state storage try (KeyValueIterator<String, ScheduledTaskEvent> iter = taskStore.all()) { while (iter.hasNext()) { KeyValue<String, ScheduledTaskEvent> entry = iter.next(); ScheduledTaskEvent task = entry.value; if (task.status() == TaskStatus.PENDING) { pendingTasks.add(task); scheduleTask(task); log.debug("Recovered pending task: {} scheduled at {}", task.taskId(), task.scheduledTime()); } } } } @Override public KeyValue<String, ScheduledTaskEvent> transform(String key, ScheduledTaskEvent event) { if (event.status() != TaskStatus.PENDING) { log.warn("Received non-pending task: {}, status: {}", event.taskId(), event.status()); return null; } removeExistingTask(event.taskId()); taskStore.put(event.taskId(), event); pendingTasks.add(event); scheduleTask(event); log.debug("Scheduled new task: {} at {}", event.taskId(), event.scheduledTime()); return null; } private void removeExistingTask(String taskId) { ScheduledTaskEvent existing = taskStore.get(taskId); if (existing != null) { // Cancel existing schedule Cancellable cancellable = cancellableMap.remove(taskId); if (cancellable != null) { cancellable.cancel(); } // Remove from pending queue pendingTasks.removeIf(task -> task.taskId().equals(taskId)); log.debug("Removed existing task: {}", taskId); } } private void scheduleTask(ScheduledTaskEvent task) { long delay = Math.max(0, task.scheduledTime() - Instant.now().getEpochSecond()); // Cancel any existing schedule for this task cancelExistingSchedule(task.taskId()); // Create accurate time schedules using stream context time Cancellable cancellable = context.schedule( Duration.ofMillis(delay), PunctuationType.WALL_CLOCK_TIME, timestamp -> executeTask(task) ); cancellable.cancel(); cancellableMap.put(task.taskId(), cancellable); log.debug("Scheduled task: {} in {} seconds", task.taskId(), delay); } private void cancelExistingSchedule(String taskId) { Cancellable existing = cancellableMap.remove(taskId); if (existing != null) { existing.cancel(); log.debug("Cancelled existing schedule for task: {}", taskId); } } private void executeTask(ScheduledTaskEvent task) { try { log.debug("Executing task: {}", task.taskId()); CommandHandler handler = handlerRegistry.getHandler(task.taskType()); if (handler == null) { throw new NoSuchElementException("No handler for type: " + task.taskType()); } // BaseCommand command = gson.fromJson(gson.toJson(task.data()), BaseCommand.class); TaskResult result = (TaskResult) handler.handle(gson.fromJson(gson.toJson(task), BetDelayAfterCommand.class)); if (result.status() == TaskStatus.EXECUTED) { ScheduledTaskEvent completedTask = ScheduledTaskEvent.markAsCompleted(task); finalizeTask(completedTask); log.debug("Task completed: {}", task.taskId()); } else { ScheduledTaskEvent failedTask = ScheduledTaskEvent.markAsFailed(task, result.errorMessage()); // Check if task should be retried if (failedTask.shouldRetry()) { long retryTime = calculateRetryTime(task); ScheduledTaskEvent retryTask = ScheduledTaskEvent.createForRetry( failedTask.taskId(), failedTask.taskType(), retryTime, failedTask.data(), failedTask.errorMessage(), failedTask.version() ); rescheduleTask(retryTask); log.warn("Task failed, scheduling retry #{} for {} at {}", retryTask.version(), task.taskId(), retryTime); } else { finalizeTask(failedTask); log.error("Task failed permanently: {}", task.taskId()); } } } catch (Exception e) { handleExecutionError(task, e); } } private void rescheduleTask(ScheduledTaskEvent retryTask) { taskStore.put(retryTask.taskId(), retryTask); pendingTasks.add(retryTask); scheduleTask(retryTask); context.forward(retryTask.taskId(), retryTask); } private void handleExecutionError(ScheduledTaskEvent task, Exception e) { log.error("Task execution error: {}", task.taskId(), e); ScheduledTaskEvent failedTask = ScheduledTaskEvent.markAsFailed(task, e.getMessage()); if (failedTask.shouldRetry()) { long retryTime = calculateRetryTime(task); ScheduledTaskEvent retryTask = ScheduledTaskEvent.createForRetry( failedTask.taskId(), failedTask.taskType(), retryTime, failedTask.data(), failedTask.errorMessage(), failedTask.version() ); rescheduleTask(retryTask); } else { finalizeTask(failedTask); } } private void finalizeTask(ScheduledTaskEvent task) { taskStore.put(task.taskId(), task); pendingTasks.removeIf(t -> t.taskId().equals(task.taskId())); cancellableMap.remove(task.taskId()); context.forward(task.taskId(), task); log.debug("Finalized task: {} with status {}", task.taskId(), task.status()); } @Override public void close() { // Clean up resources cancellableMap.values().forEach(cancellable -> { try { cancellable.cancel(); } catch (Exception e) { log.warn("Error cancelling scheduled task", e); } }); cancellableMap.clear(); pendingTasks.clear(); log.debug("ScheduledTaskTransformer closed"); } // TODO: 7/31/2025 need change or del logic private long calculateRetryTime(ScheduledTaskEvent task) { // Exponential backoff with jitter: 2^retryCount * base + random jitter int baseDelay = 30; // seconds int maxDelay = 3600; // 1 hour double jitter = 0.1 * baseDelay * (new Random().nextDouble() * 2 - 1); long delay = (long) Math.min( Math.pow(2, task.version()) * baseDelay + jitter, maxDelay ); return Instant.now().getEpochSecond() + delay; } } }
最新发布
08-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值