Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
name: docker
on:
push:
# Publish `main` as Docker `latest` image.
branches:
- main
# Publish `v1.2.3` tags as releases.
tags:
- v*.*.*
jobs:
package:
runs-on: ubuntu-latest
env:
dockerfile: Dockerfile
image_name: iomz/golemu
platforms: linux/amd64,linux/arm64
registry: ghcr.io
steps:
- uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
# list of Docker images to use as base name for tags
images: |
${{ env.registry }}/${{ env.image_name }}
# generate Docker tags based on the following events/attributes
tags: |
type=schedule
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.registry }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: "${{ env.platforms }}"
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
*.swp
sim/*
vendor/*

coverage.out
golemu
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
The MIT License (MIT)
Copyright © 2016 Iori MIZUTANI <iori.mizutani@gmail.com>
Copyright © 2025 Iori MIZUTANI <iori.mizutani@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
Expand Down
33 changes: 28 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,35 @@ Mizutani, I., & Mitsugi, J. (2016). A Multicode and Portable RFID Tag Events Emu

# Installation

Install [dep](https://github.com/golang/dep) in your system first.
## From Source

```bash
# Install the latest version
go install github.com/iomz/golemu/cmd/golemu@latest

# Or install from a local clone
git clone https://github.com/iomz/golemu.git
cd golemu
go install ./cmd/golemu

# Verify installation
golemu --help
```
$ go get github.com/iomz/golemu
$ cd $GOPATH/src/github.com/iomz/golemu
$ dep ensure && go install .

**Note:** Make sure `$GOPATH/bin` or `$HOME/go/bin` is in your `PATH` environment variable to use the `golemu` command directly.

## Build Locally

```bash
# Clone the repository
git clone https://github.com/iomz/golemu.git
cd golemu

# Build the binary
go build -o golemu ./cmd/golemu

# Run directly
./golemu --help
```

# Synopsis
Expand Down Expand Up @@ -98,4 +121,4 @@ See the LICENSE file.

## Author

Iori Mizutani (iomz)
Iori Mizutani (@iomz)
133 changes: 133 additions & 0 deletions api/handlers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

package api

import (
"net/http"

"github.com/fatih/structs"
"github.com/gin-gonic/gin"
"github.com/iomz/go-llrp"
"github.com/iomz/golemu/tag"
log "github.com/sirupsen/logrus"
)

// Handler handles API requests
type Handler struct {
tagManagerChan chan tag.Manager
}

// NewHandler creates a new API handler
func NewHandler(tagManagerChan chan tag.Manager) *Handler {
return &Handler{
tagManagerChan: tagManagerChan,
}
}

// PostTag handles tag addition requests
func (h *Handler) PostTag(c *gin.Context) {
var json []llrp.TagRecord
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request", "details": err.Error()})
return
}

if res := h.reqAddTag(json); res == "error" {
c.JSON(http.StatusConflict, gin.H{"error": "One or more tags already exist"})
} else {
c.JSON(http.StatusCreated, gin.H{"message": "Tags added successfully"})
}
}

// DeleteTag handles tag deletion requests
func (h *Handler) DeleteTag(c *gin.Context) {
var json []llrp.TagRecord
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request", "details": err.Error()})
return
}

if res := h.reqDeleteTag(json); res == "error" {
c.JSON(http.StatusNotFound, gin.H{"error": "One or more tags not found"})
} else {
c.JSON(http.StatusOK, gin.H{"message": "Tags deleted successfully"})
}
}

// GetTags handles tag retrieval requests
func (h *Handler) GetTags(c *gin.Context) {
tagList := h.reqRetrieveTag()
c.JSON(http.StatusOK, tagList)
}

func (h *Handler) reqAddTag(req []llrp.TagRecord) string {
validTags := []*llrp.Tag{}
for _, t := range req {
tagObj, err := llrp.NewTag(&llrp.TagRecord{
PCBits: t.PCBits,
EPC: t.EPC,
})
if err != nil {
log.Errorf("error creating tag: %v", err)
return "error"
}

validTags = append(validTags, tagObj)
}

for _, tagObj := range validTags {
add := tag.Manager{
Action: tag.AddTags,
Tags: []*llrp.Tag{tagObj},
}
h.tagManagerChan <- add
}

log.Debugf("add %v", req)
return "add"
}

func (h *Handler) reqDeleteTag(req []llrp.TagRecord) string {
hasError := false
for _, t := range req {
tagObj, err := llrp.NewTag(&llrp.TagRecord{
PCBits: t.PCBits,
EPC: t.EPC,
})
if err != nil {
log.Errorf("error creating tag: %v", err)
hasError = true
continue
}

deleteCmd := tag.Manager{
Action: tag.DeleteTags,
Tags: []*llrp.Tag{tagObj},
}
h.tagManagerChan <- deleteCmd
}

if hasError {
return "error"
}
log.Debugf("delete %v", req)
return "delete"
}

func (h *Handler) reqRetrieveTag() []map[string]interface{} {
retrieve := tag.Manager{
Action: tag.RetrieveTags,
Tags: []*llrp.Tag{},
}
h.tagManagerChan <- retrieve
retrieve = <-h.tagManagerChan
var tagList []map[string]interface{}
for _, tagObj := range retrieve.Tags {
t := structs.Map(llrp.NewTagRecord(*tagObj))
tagList = append(tagList, t)
}
log.Debugf("retrieve: %v", tagList)
return tagList
}
Loading
Loading