001/* 002 * Copyright (C) Photon Vision. 003 * 004 * This program is free software: you can redistribute it and/or modify 005 * it under the terms of the GNU General Public License as published by 006 * the Free Software Foundation, either version 3 of the License, or 007 * (at your option) any later version. 008 * 009 * This program is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU General Public License for more details. 013 * 014 * You should have received a copy of the GNU General Public License 015 * along with this program. If not, see <https://www.gnu.org/licenses/>. 016 */ 017 018package org.photonvision.common.networktables; 019 020import com.fasterxml.jackson.core.JsonProcessingException; 021import com.fasterxml.jackson.databind.ObjectMapper; 022import edu.wpi.first.networktables.RawPublisher; 023import java.util.HashSet; 024import java.util.Set; 025import org.photonvision.common.dataflow.structures.Packet; 026import org.photonvision.common.dataflow.structures.PacketSerde; 027 028public class PacketPublisher<T> implements AutoCloseable { 029 public final RawPublisher publisher; 030 private final PacketSerde<T> photonStruct; 031 032 public PacketPublisher(RawPublisher publisher, PacketSerde<T> photonStruct) { 033 this.publisher = publisher; 034 this.photonStruct = photonStruct; 035 036 var mapper = new ObjectMapper(); 037 try { 038 this.publisher 039 .getTopic() 040 .setProperty("message_uuid", mapper.writeValueAsString(photonStruct.getInterfaceUUID())); 041 } catch (JsonProcessingException e) { 042 // TODO Auto-generated catch block 043 e.printStackTrace(); 044 throw new RuntimeException(e); 045 } 046 addSchemaImpl(photonStruct, new HashSet<>()); 047 } 048 049 public void set(T value, int byteSize) { 050 var packet = new Packet(byteSize); 051 photonStruct.pack(packet, value); 052 publisher.set(packet.getWrittenDataCopy()); 053 } 054 055 public void set(T value) { 056 set(value, photonStruct.getMaxByteSize()); 057 } 058 059 @Override 060 public void close() { 061 publisher.close(); 062 } 063 064 /** 065 * Publish the schema for our type (and all nested types under it) to NT. 066 * 067 * <p>Copyright (c) FIRST and other WPILib contributors. Open Source Software; you can modify 068 * and/or share it under the terms of the WPILib BSD license file in the root directory of this 069 * project. 070 * 071 * @param struct The struct to publish 072 * @param seen The set of types we've already published 073 */ 074 private void addSchemaImpl(PacketSerde<?> struct, Set<String> seen) { 075 var instance = this.publisher.getTopic().getInstance(); 076 077 String typeString = struct.getTypeString(); 078 079 if (instance.hasSchema(typeString)) { 080 return; 081 } 082 083 if (!seen.add(typeString)) { 084 throw new UnsupportedOperationException(typeString + ": circular reference with " + seen); 085 } 086 087 instance.addSchema(typeString, "photonstructschema", struct.getSchema()); 088 089 for (var inner : struct.getNestedPhotonMessages()) { 090 addSchemaImpl(inner, seen); 091 } 092 for (var inner : struct.getNestedWpilibMessages()) { 093 instance.addSchema(inner); 094 } 095 seen.remove(typeString); 096 } 097}