-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NOISSUE - Add Read Property and WHOIS support #1
Open
SammyOina
wants to merge
24
commits into
absmach:main
Choose a base branch
from
SammyOina:client
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
67f2ced
add bacnet package
SammyOina 354108b
set base types and constants
SammyOina c46d913
add error classes and codes
SammyOina 2e6bbc4
encode integers
SammyOina 6c17e28
add objects
SammyOina 498161a
encoding date time and init property value
SammyOina fc6b475
add who is
SammyOina 1155568
add npdu
SammyOina b610764
testing whoIs
SammyOina 12b76cc
add apdu
SammyOina 732dc10
reorganize module
SammyOina 292c949
add read property request
SammyOina f231ed7
add read property
SammyOina 76792fa
add iam and you are
SammyOina 6b2822e
add bacnet Value
SammyOina 0c7837d
Fix error handling in BACnetValue.Decode()
SammyOina 42fcc50
Fix decoding error for object_identifier and property_identifier in R…
SammyOina b8a8db0
Fix decoding error in BACnetValue.Decode()
SammyOina 079d92b
finish implementing bacnet value
SammyOina 3eb993e
Fix issue with unnecessary print statements and add BACnet header dec…
SammyOina d2c5be9
Fix bug in readProperty.go
SammyOina e93285d
Fix import and function name in readProperty.go
SammyOina b64c033
Fix address creation in readProperty and whois.go
SammyOina c9cc370
address comments
SammyOina File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"net" | ||
"time" | ||
|
||
"github.com/absmach/bacnet/pkg/bacnet" | ||
"github.com/absmach/bacnet/pkg/encoding" | ||
"github.com/absmach/bacnet/pkg/transport" | ||
) | ||
|
||
func main() { | ||
serverIp := "127.0.0.6:47809" | ||
serverLocalAddr := "127.0.0.1:0" | ||
netType := encoding.IPV4 | ||
destination := bacnet.NewAddress(0, nil, serverIp, &netType) | ||
npdu := bacnet.NewNPDU(&destination, nil, nil, nil) | ||
npdu.Control.SetDataExpectingReply(true) | ||
npdu.Control.SetNetworkPriority(bacnet.NormalMessage) | ||
|
||
npduBytes, err := npdu.Encode() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
apdu := bacnet.APDU{ | ||
PduType: bacnet.PDUTypeConfirmedServiceRequest, | ||
ServiceChoice: byte(bacnet.ReadProperty), | ||
SegmentedResponseAccepted: false, | ||
MaxSegmentsAccepted: bacnet.MaxSegments(encoding.NoSegmentation), | ||
InvokeID: 0, | ||
} | ||
|
||
apduBytes, err := apdu.Encode() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
req := bacnet.ReadPropertyRequest{ | ||
PropertyIdentifier: encoding.PresentValue, | ||
ObjectIdentifier: &bacnet.ObjectIdentifier{Type: encoding.AnalogInput, Instance: 10}, | ||
} | ||
|
||
mes := append(npduBytes, apduBytes...) | ||
mes = append(mes, req.Encode()...) | ||
|
||
blvc, err := bacnet.NewBVLC(transport.IP) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes)+4)) | ||
message := append(blvcBytes, mes...) | ||
|
||
remoteAddr, err := net.ResolveUDPAddr("udp", serverIp) | ||
if err != nil { | ||
fmt.Println("Error resolving remote address:", err) | ||
return | ||
} | ||
|
||
localAddr, err := net.ResolveUDPAddr("udp", serverLocalAddr) | ||
if err != nil { | ||
fmt.Println("Error: ", err) | ||
return | ||
} | ||
|
||
// Create a UDP connectionBACnetAddress | ||
conn, err := net.DialUDP("udp", localAddr, remoteAddr) | ||
if err != nil { | ||
fmt.Println("Error creating UDP connection:", err) | ||
return | ||
} | ||
defer conn.Close() | ||
|
||
_, err = conn.Write(message) | ||
if err != nil { | ||
log.Fatal("Error sending WhoIsRequest:", err) | ||
} | ||
|
||
// Wait for responses | ||
buffer := make([]byte, 1500) | ||
conn.SetReadDeadline(time.Now().Add(5 * time.Second)) // Set a timeout for responses | ||
|
||
for { | ||
n, _, err := conn.ReadFromUDP(buffer) | ||
if err != nil { | ||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() { | ||
// Timeout reached, no more responses | ||
log.Println("No more responses received.") | ||
break | ||
} | ||
log.Println("Error reading response:", err) | ||
break | ||
} | ||
|
||
response := buffer[:n] | ||
blvc := bacnet.BVLC{BVLLTypeBACnetIP: blvc.BVLLTypeBACnetIP} | ||
headerLength, function, msgLength, err := blvc.Decode(response, 0) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
fmt.Printf("headerLength %v BVLCfunction %v msgLen %v\n", headerLength, function, msgLength) | ||
fmt.Println("blvc", blvc) | ||
npdu := bacnet.NPDU{Version: 1} | ||
npduLen := npdu.Decode(response, headerLength) | ||
fmt.Println("npdu", npdu) | ||
apdu := bacnet.APDU{} | ||
apduLen, err := apdu.Decode(response, headerLength+npduLen) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
fmt.Println("apdu", apdu) | ||
readPropACK := bacnet.ReadPropertyACK{} | ||
if _, err = readPropACK.Decode(response, headerLength+npduLen+apduLen-2, len(response)); err != nil { | ||
log.Fatal(err) | ||
} | ||
fmt.Println("readprop", readPropACK) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"net" | ||
"time" | ||
|
||
"github.com/absmach/bacnet/pkg/bacnet" | ||
"github.com/absmach/bacnet/pkg/encoding" | ||
"github.com/absmach/bacnet/pkg/transport" | ||
) | ||
|
||
func main() { | ||
serverIp := "127.0.0.6:47809" | ||
serverLocalAddr := "127.0.0.1:0" | ||
|
||
var highLimit, lowLimit uint32 = 4000000, 0 | ||
SammyOina marked this conversation as resolved.
Show resolved
Hide resolved
|
||
req := bacnet.WhoIs{ | ||
HighLimit: &highLimit, | ||
LowLimit: &lowLimit, | ||
} | ||
whoisBytes := req.Encode() | ||
|
||
netType := encoding.IPV4 | ||
broads := bacnet.NewAddress(encoding.MaxUint16-1, nil, serverIp, &netType) | ||
|
||
npdu := bacnet.NewNPDU(&broads, nil, nil, nil) | ||
npdu.Control.SetNetworkPriority(bacnet.NormalMessage) | ||
npduBytes, err := npdu.Encode() | ||
if err != nil { | ||
log.Fatalf("failed to encode npdu with error %v", err) | ||
} | ||
|
||
apdu := bacnet.APDU{ | ||
PduType: bacnet.PDUTypeUnconfirmedServiceRequest, | ||
ServiceChoice: byte(bacnet.ServiceChoiceWhoIs), | ||
} | ||
|
||
apduBytes, err := apdu.Encode() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
mes := append(npduBytes, apduBytes...) | ||
mes = append(mes, whoisBytes...) | ||
|
||
blvc, err := bacnet.NewBVLC(transport.IP) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes)+int(blvc.BVLCHeaderLength))) | ||
message := append(blvcBytes, mes...) | ||
|
||
remoteAddr, err := net.ResolveUDPAddr("udp", serverIp) | ||
if err != nil { | ||
log.Fatal("Error resolving remote address:", err) | ||
} | ||
|
||
localAddr, err := net.ResolveUDPAddr("udp", serverLocalAddr) | ||
if err != nil { | ||
log.Fatal("Error: ", err) | ||
return | ||
} | ||
|
||
conn, err := net.DialUDP("udp", localAddr, remoteAddr) | ||
if err != nil { | ||
log.Fatal("Error creating UDP connection:", err) | ||
} | ||
defer conn.Close() | ||
|
||
_, err = conn.Write(message) | ||
if err != nil { | ||
log.Fatal("Error sending WhoIsRequest:", err) | ||
} | ||
|
||
// Wait for responses | ||
buffer := make([]byte, 1500) | ||
SammyOina marked this conversation as resolved.
Show resolved
Hide resolved
|
||
conn.SetReadDeadline(time.Now().Add(5 * time.Second)) // Set a timeout for responses | ||
SammyOina marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
for { | ||
n, _, err := conn.ReadFromUDP(buffer) | ||
if err != nil { | ||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() { | ||
// Timeout reached, no more responses | ||
log.Println("No more responses received.") | ||
break | ||
} | ||
log.Println("Error reading response:", err) | ||
break | ||
} | ||
|
||
response := buffer[:n] | ||
log.Printf("Received response: %X\n", response) | ||
blvc := bacnet.BVLC{BVLLTypeBACnetIP: blvc.BVLLTypeBACnetIP} | ||
headerLength, function, msgLength, err := blvc.Decode(response, 0) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
fmt.Println(response) | ||
fmt.Printf("headerLength %v BVLCfunction %v msgLen %v\n", headerLength, function, msgLength) | ||
fmt.Println("blvc", blvc) | ||
fmt.Println(response[headerLength:]) | ||
npdu := bacnet.NPDU{Version: 1} | ||
npduLen := npdu.Decode(response, headerLength) | ||
fmt.Println("npdu", npdu) | ||
fmt.Println(response[headerLength+npduLen:]) | ||
apdu := bacnet.APDU{} | ||
apduLen, err := apdu.Decode(response, headerLength+npduLen) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
fmt.Println("apdu", apdu) | ||
fmt.Println(response[headerLength+npduLen+apduLen:]) | ||
iam := bacnet.IAmRequest{} | ||
iamLen, err := iam.Decode(response, headerLength+npduLen+apduLen) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
fmt.Println("iam", iam) | ||
fmt.Println(response[headerLength+npduLen+apduLen+iamLen:]) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/absmach/bacnet | ||
|
||
go 1.21.0 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package internal | ||
|
||
import "errors" | ||
|
||
var ( | ||
errBitArrayLen = errors.New("bit array length must be 8 to convert to byte") | ||
errOutOfBounds = errors.New("index is out of the range for the bitarray") | ||
) | ||
|
||
// BitArray defines an array of bits. | ||
type BitArray struct { | ||
bits []bool | ||
} | ||
|
||
// Creates a new bit array for the provided length. | ||
func NewBitArray(length int) *BitArray { | ||
return &BitArray{ | ||
bits: make([]bool, length), | ||
} | ||
} | ||
|
||
// Set sets the value of the bit array at the given index and value. | ||
func (ba *BitArray) Set(index int, value bool) error { | ||
if index >= 0 && index < len(ba.bits) { | ||
ba.bits[index] = value | ||
return nil | ||
} | ||
return errOutOfBounds | ||
} | ||
|
||
// Get returns the the value of the bit array at the given index. | ||
func (ba *BitArray) Get(index int) (bool, error) { | ||
if index >= 0 && index < len(ba.bits) { | ||
return ba.bits[index], nil | ||
} | ||
return false, errOutOfBounds | ||
} | ||
|
||
// ToByte converts bitarray to byte value. | ||
// TODO return byte array. | ||
func (ba *BitArray) ToByte() (byte, error) { | ||
// Ensure the length of the bit array is 8 to convert to a byte. | ||
if len(ba.bits) != 8 { | ||
return 0, errBitArrayLen | ||
} | ||
|
||
var byteValue byte | ||
for i := 0; i < 8; i++ { | ||
if ba.bits[i] { | ||
byteValue |= 1 << uint(7-i) | ||
} | ||
} | ||
|
||
return byteValue, nil | ||
} | ||
|
||
// NewBitArrayFromByte creates a new bit array from the given byte. | ||
// TODO check length of incoming byte. | ||
func NewBitArrayFromByte(byteValue byte) *BitArray { | ||
bitArray := NewBitArray(8) | ||
for j := 0; j < 8; j++ { | ||
bitArray.Set(j, byteValue&(1<<uint(7-j)) != 0) | ||
} | ||
return bitArray | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The package name seems odd.
bacnet/pkg/bacnet
. Why not move bacnet to the root of the project as this repository is bacnet package