<commit_before>package uavtalkconnection

import (
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/openflylab/bridge/common"
	"github.com/openflylab/bridge/dispatcher"
)

/*
 * This is where we manage the whole usb layer.
 * States are used to manage handshake and session management.
 * See https://github.com/TauLabs/TauLabs/wiki/UAVTalk-session-management
 * and https://wiki.openpilot.org/display/WIKI/UAVTalk
**/

type stateHolder struct {
	connection *dispatcher.Connection
	inChan     chan Packet
	outChan    chan Packet

	state state
}

func (sh *stateHolder) setState(s state) {
	sh.state = s
	sh.state.start()
}

type state interface {
	start()
	in(Packet) bool  // packets coming from the dispatcher
	out(Packet) bool // packets coming from the flight controller
}

type notConnected struct {
	stateHolder *stateHolder

	flightTelemetryStats *common.Definition
}

func (s *notConnected) start() {
	var err error
	s.flightTelemetryStats, err = definitions.GetDefinitionForName("FlightTelemetryStats")
	if err != nil {
		log.Fatal(err)
	}

	log.Info("Started notConnected state")

	handshakeReq := createGCSTelemetryStatsObjectPacket("HandshakeReq")
	s.stateHolder.inChan <- handshakeReq
}

func (s *notConnected) in(p Packet) bool {
	return false
}

func (s *notConnected) out(p Packet) bool {
	if p.definition == s.flightTelemetryStats {
		log.Info(p.data["Status"])
		if p.data["Status"] == "Disconnected" {
			handshakeReq := createGCSTelemetryStatsObjectPacket("HandshakeReq")
			s.stateHolder.inChan <- handshakeReq
		} else if p.data["Status"] == "HandshakeAck" {
			handshakeConnected := createGCSTelemetryStatsObjectPacket("Connected")
			s.stateHolder.inChan <- handshakeConnected
		} else if p.data["Status"] == "Connected" {
			s.stateHolder.setState(&noSession{stateHolder: s.stateHolder})
		}
	}
	return false
}

const noSessionStateFirstSend = 1
const noSessionStateCreateSession = 2
const noSessionStateFetchObjects = 3

type noSession struct {
	stateHolder *stateHolder

	currentSessionStateCreationStep int
	currentObjectID                 uint8
	numberOfObjects                 uint8

	sessionManaging *common.Definition
}

func (s *noSession) start() {
	log.Info("Started noSession state")

	s.currentSessionStateCreationStep = noSessionStateFirstSend

	var err error
	s.sessionManaging, err = definitions.GetDefinitionForName("SessionManaging")
	if err != nil {
		log.Fatal(err)
	}

	sessionManagingReq := createSessionManagingRequest()
	s.stateHolder.inChan <- sessionManagingReq
}

func (s *noSession) in(p Packet) bool {
	return false
}

func (s *noSession) out(p Packet) bool {
	if p.definition == s.sessionManaging {
		if p.cmd == objectCmd || p.cmd == objectCmdWithAck {
			log.Infof("%d %d %d %d %d", *(p.data["SessionID"].(*uint16)), *(p.data["ObjectID"].(*uint32)), *(p.data["ObjectInstances"].(*uint8)), *(p.data["NumberOfObjects"].(*uint8)), *(p.data["ObjectOfInterestIndex"].(*uint8)))
			numberOfObjects := *(p.data["NumberOfObjects"].(*uint8))
			if numberOfObjects != 0 {
				s.numberOfObjects = numberOfObjects - 1
			}
			if p.cmd == objectCmdWithAck {
				log.Info("objectCmdWithAck")
				sessionManagingPacketAck := createSessionManagingPacketAck()
				s.stateHolder.inChan <- sessionManagingPacketAck

				sessionManagingPacket := createSessionManagingPacket(4224, s.currentObjectID)
				s.currentObjectID++
				s.currentSessionStateCreationStep = noSessionStateFetchObjects
				s.stateHolder.inChan <- sessionManagingPacket

				if s.currentObjectID > s.numberOfObjects {
					s.stateHolder.setState(&stream{})
				}
			} else {
				sessionManagingPacket := createSessionManagingPacket(0, 0)
				s.stateHolder.inChan <- sessionManagingPacket
			}
		} else if p.cmd == objectAck {
			log.Info("Received Ack for SessionManaging")
		} else if p.cmd == objectNack {
			log.Info("Received Nack for SessionManaging")
			// TODO Failsafe...
		}
	}
	return false<commit_msg>fix flight controller when reaching last sessionmanaging uavo<commit_after>package uavtalkconnection

import (
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/openflylab/bridge/common"
	"github.com/openflylab/bridge/dispatcher"
)

/*
 * This is where we manage the whole usb layer.
 * States are used to manage handshake and session management.
 * See https://github.com/TauLabs/TauLabs/wiki/UAVTalk-session-management
 * and https://wiki.openpilot.org/display/WIKI/UAVTalk
**/

type stateHolder struct {
	connection *dispatcher.Connection
	inChan     chan Packet
	outChan    chan Packet

	state state
}

func (sh *stateHolder) setState(s state) {
	sh.state = s
	sh.state.start()
}

type state interface {
	start()
	in(Packet) bool  // packets coming from the dispatcher
	out(Packet) bool // packets coming from the flight controller
}

type notConnected struct {
	stateHolder *stateHolder

	flightTelemetryStats *common.Definition
}

func (s *notConnected) start() {
	var err error
	s.flightTelemetryStats, err = definitions.GetDefinitionForName("FlightTelemetryStats")
	if err != nil {
		log.Fatal(err)
	}

	log.Info("Started notConnected state")

	handshakeReq := createGCSTelemetryStatsObjectPacket("HandshakeReq")
	s.stateHolder.inChan <- handshakeReq
}

func (s *notConnected) in(p Packet) bool {
	return false
}

func (s *notConnected) out(p Packet) bool {
	if p.definition == s.flightTelemetryStats {
		log.Info(p.data["Status"])
		if p.data["Status"] == "Disconnected" {
			handshakeReq := createGCSTelemetryStatsObjectPacket("HandshakeReq")
			s.stateHolder.inChan <- handshakeReq
		} else if p.data["Status"] == "HandshakeAck" {
			handshakeConnected := createGCSTelemetryStatsObjectPacket("Connected")
			s.stateHolder.inChan <- handshakeConnected
		} else if p.data["Status"] == "Connected" {
			s.stateHolder.setState(&noSession{stateHolder: s.stateHolder})
		}
	}
	return false
}

const noSessionStateFirstSend = 1
const noSessionStateCreateSession = 2
const noSessionStateFetchObjects = 3

type noSession struct {
	stateHolder *stateHolder

	currentSessionStateCreationStep int
	currentObjectID                 uint8
	numberOfObjects                 uint8

	sessionManaging *common.Definition
}

func (s *noSession) start() {
	log.Info("Started noSession state")

	s.currentSessionStateCreationStep = noSessionStateFirstSend

	var err error
	s.sessionManaging, err = definitions.GetDefinitionForName("SessionManaging")
	if err != nil {
		log.Fatal(err)
	}

	sessionManagingReq := createSessionManagingRequest()
	s.stateHolder.inChan <- sessionManagingReq
}

func (s *noSession) in(p Packet) bool {
	return false
}

func (s *noSession) out(p Packet) bool {
	if p.definition == s.sessionManaging {
		if p.cmd == objectCmd || p.cmd == objectCmdWithAck {
			log.Infof("%d %d %d %d %d", *(p.data["SessionID"].(*uint16)), *(p.data["ObjectID"].(*uint32)), *(p.data["ObjectInstances"].(*uint8)), *(p.data["NumberOfObjects"].(*uint8)), *(p.data["ObjectOfInterestIndex"].(*uint8)))
			numberOfObjects := *(p.data["NumberOfObjects"].(*uint8))
			if numberOfObjects != 0 {
				s.numberOfObjects = numberOfObjects
			}
			if p.cmd == objectCmdWithAck {
				log.Info("objectCmdWithAck")
				sessionManagingPacketAck := createSessionManagingPacketAck()
				s.stateHolder.inChan <- sessionManagingPacketAck

				if s.currentObjectID >= s.numberOfObjects {
					s.stateHolder.setState(&stream{})
					return false
				}

				sessionManagingPacket := createSessionManagingPacket(4224, s.currentObjectID)
				s.currentObjectID++
				s.currentSessionStateCreationStep = noSessionStateFetchObjects
				s.stateHolder.inChan <- sessionManagingPacket
			} else {
				sessionManagingPacket := createSessionManagingPacket(0, 0)
				s.stateHolder.inChan <- sessionManagingPacket
			}
		} else if p.cmd == objectAck {
			log.Info("Received Ack for SessionManaging")
		} else if p.cmd == objectNack {
			log.Info("Received Nack for SessionManaging")
			// TODO Failsafe...
		}
	}
	return false
{'fraction_non_alphanumeric': 0.11755783086841107, 'fraction_numerical': 0.005182657059790165, 'mean_word_length': 4.449035812672176, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5258164', 'n_tokens_mistral': 2788, 'n_tokens_neox': 2516, 'n_words': 547}