This commit is contained in:
Albert Espín 2024-10-01 20:28:58 +02:00
commit 2dfbaef6d6
26 changed files with 1052 additions and 0 deletions

0
LICENSE Normal file
View File

0
README.md Normal file
View File

133
barcode/app/app.go Normal file
View File

@ -0,0 +1,133 @@
package app
import (
"bytes"
"context"
"encoding/json"
"fmt"
"os"
"os/signal"
"strings"
"syscall"
cml04eventer "git.espin.casa/albert/cml04-eventer"
"git.espin.casa/albert/cml04-falcon-system/internal/storage"
"git.espin.casa/albert/cml04-falcon-system/internal/types"
"git.espin.casa/albert/logger"
"github.com/nats-io/nats.go"
"github.com/spf13/cobra"
)
func Run(cmd *cobra.Command, args []string) {
// read flags
logLevel, _ := cmd.Flags().GetString("log-level")
userName, _ := cmd.Flags().GetString("db-username")
userPass, _ := cmd.Flags().GetString("db-password")
dbHost, _ := cmd.Flags().GetString("db-host")
dbPort, _ := cmd.Flags().GetInt("db-port")
dbName, _ := cmd.Flags().GetString("db-name")
natsHost, _ := cmd.Flags().GetString("nats-host")
natsPort, _ := cmd.Flags().GetInt("nats-port")
// setup logger
log := logger.New(os.Stdout, logLevel)
// log fields
logFields := logger.LogFields{
"db_username": userName,
"db_password": "*****",
"db_host": dbHost,
"db_port": dbPort,
"db_name": dbName,
"nats_host": natsHost,
"nats_port": natsPort,
"log_level": logLevel,
}
// create storager
storage, err := storage.New(&storage.DBConfig{
Username: userName,
Password: userPass,
Host: dbHost,
Port: dbPort,
Name: dbName,
})
// handler error
if err != nil {
log.Error("create storage failed", err, logFields)
return
}
// NATS connect
nc, err := nats.Connect(fmt.Sprintf("nats://%s:%d", natsHost, natsPort))
if err != nil {
log.Error("create nats connection failed", err, logFields)
return
}
defer nc.Close()
// create context
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// NATS subscribe subject
nc.Subscribe("barcode.new", func(msg *nats.Msg) {
go func(log logger.LoggerAdapter) {
if err := ProcessMessage(ctx, msg, storage, log); err != nil {
log.Error("process message failed", err, logger.LogFields{})
return
}
}(log)
})
// info banner
log.Info("started falcon barcoder service", logFields)
// wait signal to finish
signal := WaitSignal()
log.Info("signal received", logFields.Add(logger.LogFields{
"signal": signal,
}))
}
func LoadingBed(barcode string) types.LoadingBed {
if strings.HasPrefix(barcode, "940") {
return types.ATA12
}
return types.ATA345
}
func ProcessMessage(ctx context.Context, msg *nats.Msg, storage storage.Storager, log logger.LoggerAdapter) error {
// event holder
event := &cml04eventer.Event{}
// create new buffer based on message data
buff := bytes.NewBuffer(msg.Data)
// decode message
if err := json.NewDecoder(buff).Decode(event); err != nil {
return err
}
// info banner
log.Info("received event bus message", logger.LogFields{
"event_id": event.EventID,
"event_topic": event.EventTopic,
})
// barcode
bar := string(event.EventData)
// create and fill barcode type
barcode := &types.Barcode{
Barcode: bar,
LoadingBed: LoadingBed(bar),
}
// store barcode
return storage.StoreBarcode(ctx, barcode)
}
// WaitSignal catching exit signal
func WaitSignal() os.Signal {
ch := make(chan os.Signal, 2)
signal.Notify(
ch,
syscall.SIGINT,
syscall.SIGQUIT,
syscall.SIGTERM,
)
for {
sig := <-ch
switch sig {
case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM:
return sig
}
}
}

19
barcode_event.json Normal file
View File

@ -0,0 +1,19 @@
{
"event_id": "99260667-d229-4a24-9c1c-156f8cdc16fb",
"event_topic": "barcode.new",
"event_sender": "tester",
"event_meta": null,
"event_data": [
57,
52,
48,
49,
50,
51,
52,
53,
54,
55
],
"event_time": "2024-10-01T15:39:55+00:00"
}

21
cert.pem Normal file
View File

@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUNNi2pceulClb37YuXcB30pmBcFgwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCRVMxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDA5MjUwNzM4NTNaFw0zNDA5
MjMwNzM4NTNaMEUxCzAJBgNVBAYTAkVTMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQC8QOsVxvWna0zailcP7Ij/AhYOjbtQ2MWE3V/KucFP
/3zZPfzatz+ejMyp5x3qnSdonAqP6nn2PJ1coNTSXuVKWSXsWpcMeHXlHY06XRp4
WDSWw76LWr67GChp0gIWQ2XbZTmXloKbzsuZQkGJONSbzE90ljIVmc2+yR5hz+5r
waGpIQS9YP8vpVZgSrVPtAbun/qVvKyblZvGjncygGvFrejImrAnd1UTBYFIjCek
ugx9y08CSzUTFJmOihsRtxjc58Ui9AQuwZHqsy79cBTTjCueEjXUG3Rqf2/yMkar
JvMHbRnZ6bwsrkKB65ZzOgiFTLoPzQnCM1AHfwcS0fznAgMBAAGjUzBRMB0GA1Ud
DgQWBBSf6+GNxqh7T3TvOOaYj2VrM8M/bzAfBgNVHSMEGDAWgBSf6+GNxqh7T3Tv
OOaYj2VrM8M/bzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAA
DqkHYEPi1WAkDmtF5KYYzIGgQ/wCsFYpC0dlU4u31XkEL5AkbiRHgin7rd6Qrpz0
vJ+xkqulX+v+5aIayIyD0bDvEmUl/o0OtKoYead4+Y80EgOEd8Lmmaui5RnrPE71
Y+EzRfsL1xj7Kkil8Sp25wh/liPwegw0LaaP5wzYd+CaEbW1+EDXf91beNKHl8i+
7o9wBBXMjL67Am6B2FeKTqh4uEyx4SS8u/O0KrtzFaax3xbuodNginuI4poawqXg
4VwLz6G+wgh1KAZB1Mfrx1dgg3xnw36WWGkAiLMO4St8EPPE5s4B50nENUqCddRc
Eod6mr6PWI2GJG3vFE+a
-----END CERTIFICATE-----

30
cmd/barcode.go Normal file
View File

@ -0,0 +1,30 @@
/*
Copyright © 2024 Albert Espín aespin@gcelsa.com
*/
package cmd
import (
"git.espin.casa/albert/cml04-falcon-system/barcode/app"
"github.com/spf13/cobra"
)
// barcoderCmd represents the barcoder command
var barcoderCmd = &cobra.Command{
Use: "barcode",
Short: "Barcode service handler.",
Long: "Barcode service handles readings from handsets devices or printing robot vision.",
Run: app.Run,
}
func init() {
rootCmd.AddCommand(barcoderCmd)
// flags
barcoderCmd.Flags().String("db-username", "postgres", "database username")
barcoderCmd.Flags().String("db-password", "Me8140@01", "database user password")
barcoderCmd.Flags().String("db-host", "10.136.49.104", "database host address")
barcoderCmd.Flags().Int("db-port", 5432, "database tcp port")
barcoderCmd.Flags().String("db-name", "falcon", "database user password")
barcoderCmd.Flags().String("nats-host", "10.136.49.95", "nats.io broker host address")
barcoderCmd.Flags().Int("nats-port", 4222, "nats.io broker tcp port")
barcoderCmd.Flags().String("log-level", "debug", "log level trace")
}

40
cmd/bundle.go Normal file
View File

@ -0,0 +1,40 @@
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
// bundleCmd represents the bundle command
var bundleCmd = &cobra.Command{
Use: "bundle",
Short: "A brief description of your command",
Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("bundle called")
},
}
func init() {
rootCmd.AddCommand(bundleCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// bundleCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// bundleCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

36
cmd/handset.go Normal file
View File

@ -0,0 +1,36 @@
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cmd
import (
"git.espin.casa/albert/cml04-falcon-system/handset/app"
"github.com/spf13/cobra"
)
// handsetCmd represents the handset command
var handsetCmd = &cobra.Command{
Use: "handset",
Short: "A brief description of your command",
Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
Run: app.Run,
}
func init() {
rootCmd.AddCommand(handsetCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// handsetCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// handsetCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

38
cmd/root.go Normal file
View File

@ -0,0 +1,38 @@
/*
Copyright © 2024 Albert Espín aespin@gcelsa.com
*/
package cmd
import (
"os"
"github.com/spf13/cobra"
)
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "cml04-falcon-system",
Short: "Falcon system sevices",
Long: `Falcon system sevices. Control and manage production data`,
}
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cml04-falcon-system.yaml)")
// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

35
cmd/sap.go Normal file
View File

@ -0,0 +1,35 @@
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cmd
import (
"git.espin.casa/albert/cml04-falcon-system/sap/app"
"github.com/spf13/cobra"
)
// sapCmd represents the sap command
var sapCmd = &cobra.Command{
Use: "sap",
Short: "A brief description of your command",
Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
Run: app.Run,
}
func init() {
rootCmd.AddCommand(sapCmd)
sapCmd.Flags().String("db-username", "postgres", "database username")
sapCmd.Flags().String("db-password", "Me8140@01", "database user password")
sapCmd.Flags().String("db-host", "10.136.49.104", "database host address")
sapCmd.Flags().Int("db-port", 5432, "database tcp port")
sapCmd.Flags().String("db-name", "falcon", "database user password")
sapCmd.Flags().String("nats-host", "10.136.49.95", "nats.io broker host address")
sapCmd.Flags().Int("nats-port", 4222, "nats.io broker tcp port")
sapCmd.Flags().String("log-level", "debug", "log level trace")
}

39
go.mod Normal file
View File

@ -0,0 +1,39 @@
module git.espin.casa/albert/cml04-falcon-system
go 1.23.1
require (
git.espin.casa/albert/cml04-eventer v1.0.0
github.com/spf13/cobra v1.8.1
gorm.io/gorm v1.25.12
)
require (
github.com/golang/snappy v0.0.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/nats-io/nkeys v0.4.7 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/nsqio/go-nsq v1.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.18.0 // indirect
)
require (
git.espin.casa/albert/logger v1.0.0
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/julienschmidt/httprouter v1.3.0
github.com/nats-io/nats.go v1.37.0
github.com/spf13/pflag v1.0.5 // indirect
gorm.io/driver/postgres v1.5.9
)

71
go.sum Normal file
View File

@ -0,0 +1,71 @@
git.espin.casa/albert/cml04-eventer v1.0.0 h1:DtYEQ2uDB3A19BDFnG03zR/yUKxLcpZgCKmJw+xnX+s=
git.espin.casa/albert/cml04-eventer v1.0.0/go.mod h1:BSOrrtf40FbgxbaUg12ti55Lyd3L8O4oBZz5r6ag1+Y=
git.espin.casa/albert/logger v1.0.0 h1:DF+SwwkptiZBiB1HUIPcKRRoLuUC7fVUfnF/I9p5Cj4=
git.espin.casa/albert/logger v1.0.0/go.mod h1:TXbZ7mayDtJvcs+DucVbs2klio9jq5k1eWFZ2wxgRGM=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE=
github.com/nats-io/nats.go v1.37.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nsqio/go-nsq v1.1.0 h1:PQg+xxiUjA7V+TLdXw7nVrJ5Jbl3sN86EhGCQj4+FYE=
github.com/nsqio/go-nsq v1.1.0/go.mod h1:vKq36oyeVXgsS5Q8YEO7WghqidAVXQlcFxzQbQTuDEY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8=
gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=

29
handset/app/app.go Normal file
View File

@ -0,0 +1,29 @@
package app
import (
"os"
"os/signal"
"syscall"
"github.com/spf13/cobra"
)
func Run(cmd *cobra.Command, args []string) {}
// WaitSignal catching exit signal
func WaitSignal() os.Signal {
ch := make(chan os.Signal, 2)
signal.Notify(
ch,
syscall.SIGINT,
syscall.SIGQUIT,
syscall.SIGTERM,
)
for {
sig := <-ch
switch sig {
case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM:
return sig
}
}
}

View File

@ -0,0 +1,38 @@
package eventer
import (
"bytes"
"context"
"encoding/json"
cml04eventer "git.espin.casa/albert/cml04-eventer"
"github.com/nats-io/nats.go"
)
type Eventer interface {
BarCode(ctx context.Context, barcode string) error
}
type eventer struct {
nc *nats.Conn
}
func (e *eventer) BarCode(ctx context.Context, barcode string) error {
// create event message
evt := cml04eventer.NewEvent("handset", "barcode.new", nil, []byte(barcode))
buf := bytes.Buffer{}
if err := json.NewEncoder(&buf).Encode(evt); err != nil {
return err
}
return e.nc.Publish("barcode.new", buf.Bytes())
}
func New() (Eventer, error) {
return &eventer{
nc: &nats.Conn{},
}
}

View File

@ -0,0 +1,17 @@
package handlers
import (
"net/http"
"git.espin.casa/albert/cml04-falcon-system/handset/eventer"
"github.com/julienschmidt/httprouter"
)
func BarCodeHandler(eventer eventer.Eventer) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
barcode := ps.ByName("barcode")
if err := eventer.BarCode(r.Context(), barcode); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}

19
handset/handlers/index.go Normal file
View File

@ -0,0 +1,19 @@
package handlers
import (
"html/template"
"net/http"
"github.com/julienschmidt/httprouter"
)
func IndexHandler() httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
t, _ := template.ParseFiles("templates/index.html")
err := t.Execute(w, nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
}

12
handset/routes/routes.go Normal file
View File

@ -0,0 +1,12 @@
package routes
import (
"git.espin.casa/albert/cml04-falcon-system/handset/eventer"
"git.espin.casa/albert/cml04-falcon-system/handset/handlers"
"github.com/julienschmidt/httprouter"
)
func CreateRoutes(r *httprouter.Router, eventer eventer.Eventer) {
r.GET("/", handlers.IndexHandler())
r.GET("/barcode/:barcode", handlers.BarCodeHandler(eventer))
}

View File

@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/assets/css/bulma.min.css">
<script src="/assets/js/html5-qrcode.min.js"></script>
<title>Falcon Handset UI</title>
</head>
<body>
<h1>Scanner de códigos de barras</h1>
<div id="read-result"></div>
<div style="display: flex; justify-content: center;">
<div id="my-qr-reader" style="width:500px;"></div>
</div>
<script>
function domReady(fn) {
if (document.readyState === "complete" || document.readyState === "interactive") {
setTimeout(fn, 1);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
domReady(function () {
var myqr = document.getElementById('read-result')
var lastResult, countResults = 0;
function checkText(decodeText) {
const startsWith = ['940', '945'];
if (!startsWith.includes(decodeText.substring(0, 3))) {
return false;
}
if (decodeText.length !== 10) {
return false;
}
return true;
}
function onScanSuccess(decodeText, decodeResult) {
if (decodeText !== lastResult) {
if (!checkText(decodeText)) {
alert("El código de barras leído no es valido");
return
}
++countResults;
lastResult = decodeText;
fetch('/barcode/' + decodeText)
.then(response => {
if (!response.ok) {
throw new Error(`Respuesta no exitosa ${response.status}`);
}
return response.json();
})
.then(data => {
console.log('data:', data); // Reemplaza por la forma en que deseas usar los datos
})
.catch(error => {
console.error('barcode error:', error);
});
alert("codigo de barras: " + decodeText, decodeResult);
myqr.innerHTML = ` ${countResults} : ${decodeText} `;
}
}
var htmlscanner = new Html5QrcodeScanner(
"my-qr-reader",
{
fps: 10,
qrbox: 250
}
)
htmlscanner.render(onScanSuccess);
})
</script>
</body>
</html>

View File

@ -0,0 +1,75 @@
package storage
import (
"context"
"fmt"
"git.espin.casa/albert/cml04-falcon-system/internal/types"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Storager interface {
StoreBarcode(ctx context.Context, in *types.Barcode) error
}
type storage struct {
db *gorm.DB
}
type DBConfig struct {
Username string
Password string
Host string
Port int
Name string
}
// StoreBarcode implements IStorage.
func (s *storage) StoreBarcode(ctx context.Context, in *types.Barcode) error {
return s.db.Save(in).Error
}
func ProductionDataBase(conf *DBConfig) (*gorm.DB, error) {
// create dsn string
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable TimeZone=Europe/Madrid",
conf.Host,
conf.Username,
conf.Password,
conf.Name,
conf.Port,
)
// create open database connection
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
return nil, err
}
return db, nil
}
func Automigrate(db *gorm.DB) error {
return db.AutoMigrate(
&types.Barcode{},
&types.BundleData{},
&types.ProductionOrder{},
)
}
func New(conf *DBConfig) (Storager, error) {
// database holder
var db *gorm.DB
// producctio
db, err := ProductionDataBase(conf)
if err != nil {
return nil, err
}
// auto migration
if err := Automigrate(db); err != nil {
return nil, err
}
// done
return &storage{
db: db,
}, nil
}

24
internal/types/barcode.go Normal file
View File

@ -0,0 +1,24 @@
package types
import (
"time"
"gorm.io/gorm"
)
type BarcodeStatus uint16
type LoadingBed uint8
const (
ATA12 LoadingBed = iota + 1
ATA345
)
type Barcode struct {
Barcode string `gorm:"primaryKey"`
LoadingBed LoadingBed
CreatedAt time.Time `gorm:"->;<-:create" json:"createdat,omitempty"`
UpdatedAt time.Time `json:"updatedat,omitempty"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deletedat,omitempty"`
}

164
internal/types/bundle.go Normal file
View File

@ -0,0 +1,164 @@
package types
import (
"fmt"
"time"
"gorm.io/gorm"
)
type BundleData struct {
Grupo6 string `json:"grupo6"`
Po int `gorm:"index" json:"po"`
Co int `json:"co"`
Colada string `json:"colada"`
Calidad string `json:"calidad"`
Matnr string `json:"matnr"`
Dibujo int `json:"dibujo"`
Operador string `json:"operador"`
Serie int `json:"serie"`
Nromatricula string `gorm:"primaryKey" json:"nromatricula"`
NroBulto string `json:"nro_bulto"`
EtiquetaDoble string `json:"etiqueta_doble"`
Fecha int `json:"fecha"`
Turno string `json:"turno"`
Observacion1 string `json:"observacion1"`
Observacion2 string `json:"observacion2"`
Observacion3 string `json:"observacion3"`
PaqueteLongitud float64 `json:"paquete_longitud"`
PaqueteAncho int `json:"paquete_ancho"`
PaqueteAlto float64 `json:"paquete_alto"`
PaquetePeso int `json:"paquete_peso"`
PaqueteNroSecciones int `json:"paquete_nro_secciones"`
PaqueteNroMantos int `json:"paquete_nro_mantos"`
PaqueteNroSeccManto int `json:"paquete_nro_secc_manto"`
SeccionTipo string `gorm:"index" json:"seccion_tipo"`
SeccionLongitud int `json:"seccion_longitud"`
SeccionAncho int `json:"seccion_ancho"`
SeccionAlto int `json:"seccion_alto"`
Idioma string `json:"idioma"`
Destino int `json:"destino"`
Hora int `json:"hora"`
Horario int `json:"horario"`
Inst string `json:"inst"`
Tren int `json:"tren"`
Normed string `json:"normed"`
Norpro string `json:"norpro"`
Nortol string `json:"nortol"`
Spras string `json:"spras"`
Statu int `json:"statu"`
Crlf string `json:"crlf"`
Maquina int `json:"maquina"`
Padre string `json:"padre"`
Paqpadre string `json:"paqpadre"`
RelevantTime string `json:"relevant_time"`
Desvio float64 `json:"desvio"`
Pesoteorico float64 `json:"pesoteorico"`
PesoteoricoReal float64 `json:"pesoteorico_real"`
DesvioTeoricoReal float64 `json:"desvio_teorico_real"`
FechaImpresion string `json:"fecha_impresion"`
PesoNivel1 float64 `json:"peso_nivel1"`
L3Sended bool `json:"l3_sended,omitempty"`
Confirmed bool `json:"confirmed,omitempty"`
SAP bool `json:"sap,omitempty"`
CreatedAt time.Time `gorm:"->;<-:create" json:"createdat,omitempty"`
UpdatedAt time.Time `json:"updatedat,omitempty"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deletedat,omitempty"`
}
func (BundleData) TableName() string {
return "bundles"
}
func (b *BundleData) BeforeSave(tx *gorm.DB) error {
// calculate and assign teorical weight
PesoTeorico(b)
// calculation of the deviation of the actual weight from the theoretical weight
if err := Desvio(b); err != nil {
return err
}
// calculation of the "real" theorical weight means lenght + the lenght of the disc saw (10mm)
PesoTeoricoReal(b)
if err := DesvioReal(b); err != nil {
return err
}
// calculation of the deviation between theorical and SAP
if err := PesoDesvioSAP(b); err != nil {
return err
}
return nil
}
func PesoTeorico(b *BundleData) {
// get the lenght of the bundle
bl := b.PaqueteLongitud
// weight per meter
bw := b.PaqueteAlto
// number of pieces
bp := b.PaqueteNroSecciones
// calculate theoretical weight
bt := bl * bw * float64(bp)
// set value
b.Pesoteorico = bt
}
func Desvio(b *BundleData) error {
// check if theorical is 0
if b.Pesoteorico == 0 {
return fmt.Errorf("theorical weight is zero")
}
// calculate deviation
dv := float64(b.PaquetePeso) - (b.Pesoteorico)
// % of deviation
pdv := (dv / float64(b.Pesoteorico)) * 100
// set value
b.Desvio = pdv
// done
return nil
}
func PesoTeoricoReal(b *BundleData) {
// get the lenght of the bundle
bl := b.PaqueteLongitud + 0.01 // added 10 mm
// weight per meter
bw := b.PaqueteAlto
// number of pieces
bp := b.PaqueteNroSecciones
// calculate theoretical weight
bt := bl * bw * float64(bp)
// set value
b.PesoteoricoReal = bt
}
func DesvioReal(b *BundleData) error {
// check if theorical is 0
if b.PesoteoricoReal == 0 {
return fmt.Errorf("theorical weight is zero")
}
// calculate deviation
dv := float64(b.PaquetePeso) - (b.PesoteoricoReal)
// % of deviation
pdv := (dv / float64(b.PesoteoricoReal)) * 100
// set value
b.DesvioTeoricoReal = pdv
// done
return nil
}
func PesoDesvioSAP(b *BundleData) error {
// check if theorical is 0
if b.Pesoteorico == 0 {
return fmt.Errorf("theorical weight is zero")
}
// check if SAP deviation is 0
if b.PesoNivel1 == 0 {
return fmt.Errorf("SAP deviation not found")
}
// get deviation
dvs := b.PesoNivel1
// calculates weight
res := b.Pesoteorico + (b.Pesoteorico * (dvs / 100))
// set weight value
b.PesoNivel1 = res
return nil
}

View File

@ -0,0 +1,78 @@
package types
import (
"time"
"gorm.io/gorm"
)
type ProductionOrder struct {
Inst string `json:"INST"`
DateTime string `json:"DATE_TIME"`
POrderNo int `json:"P_ORDER_NO" gorm:"primaryKey"`
SchedulNo int `json:"SCHEDUL_NO"`
SeqNumber int `json:"SEQ_NUMBER"`
PptimeWfc string `json:"PPTIME_WFC"`
PptimeMsc string `json:"PPTIME_MSC"`
SteelGrad string `json:"STEEL_GRAD"`
ITemp string `json:"I_TEMP"`
IHeight string `json:"I_HEIGHT"`
IWidth string `json:"I_WIDTH"`
ISection string `json:"I_SECTION"`
HeatingSt int `json:"HEATING_ST"`
FTarTemp string `json:"F_TAR_TEMP"`
FSection string `json:"F_SECTION"`
FSectType string `json:"F_SECT_TYPE"`
TotWeight string `json:"TOT_WEIGHT"`
TBeamBla int `json:"T_BEAM_BLA"`
TCustOrd int `json:"T_CUST_ORD"`
TestLen int `json:"TEST_LEN"`
PostFlag string `json:"POST_FLAG"`
ModuloX string `json:"MODULO_X"`
OvWTolU string `json:"OV_W_TOL_U"`
OvWTolL string `json:"OV_W_TOL_L"`
OvHTolU string `json:"OV_H_TOL_U"`
OvHTolL string `json:"OV_H_TOL_L"`
WeTTolU string `json:"WE_T_TOL_U"`
WeTTolL string `json:"WE_T_TOL_L"`
WeHTolU string `json:"WE_H_TOL_U"`
WeHTolL string `json:"WE_H_TOL_L"`
FlWDsU string `json:"FL_W_DS_U"`
FlWDsL string `json:"FL_W_DS_L"`
FlWOsU string `json:"FL_W_OS_U"`
FlWOsL string `json:"FL_W_OS_L"`
WeMetTU string `json:"WE_MET_T_U"`
WeMetTL string `json:"WE_MET_T_L"`
WeCenTol string `json:"WE_CEN_TOL"`
WeSquTol string `json:"WE_SQU_TOL"`
FlParTol string `json:"FL_PAR_TOL"`
BdRollID string `json:"BD_ROLL_ID"`
UrRollID string `json:"UR_ROLL_ID"`
EdRollID string `json:"ED_ROLL_ID"`
UfRollID string `json:"UF_ROLL_ID"`
SmRollID string `json:"SM_ROLL_ID"`
Grupo6 string `json:"GRUPO6"`
StName string `json:"ST_NAME"`
StWeighM string `json:"ST_WEIGH_M"`
StLen1 string `json:"ST_LEN_1"`
StLen2 string `json:"ST_LEN_2"`
StLen3 string `json:"ST_LEN_3"`
StLen4 string `json:"ST_LEN_4"`
StLen5 string `json:"ST_LEN_5"`
StLen6 string `json:"ST_LEN_6"`
StLen7 string `json:"ST_LEN_7"`
StLen8 string `json:"ST_LEN_8"`
StLen9 string `json:"ST_LEN_9"`
StLen10 string `json:"ST_LEN_10"`
StLen11 string `json:"ST_LEN_11"`
StLen12 string `json:"ST_LEN_12"`
Marfab int `json:"MARFAB"`
Sortb string `json:"SORTB"`
CreatedAt time.Time `gorm:"->;<-:create" json:"createdat,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
DeletedAt gorm.DeletedAt `gorm:"index"`
}
func (ProductionOrder) TableName() string {
return "sap_po"
}

11
main.go Normal file
View File

@ -0,0 +1,11 @@
/*
Copyright © 2024 Albert Espín aespin@gcelsa.com
*/
package main
import "git.espin.casa/albert/cml04-falcon-system/cmd"
func main() {
cmd.Execute()
}

5
sap/app/app.go Normal file
View File

@ -0,0 +1,5 @@
package app
import "github.com/spf13/cobra"
func Run(cmd *cobra.Command, args []string) {}

14
server.crt Normal file
View File

@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICHTCCAaKgAwIBAgIUEnhK7IvUaUbu6Q1mSpsfTtg55NUwCgYIKoZIzj0EAwIw
RTELMAkGA1UEBhMCRVMxEjAQBgNVBAgMCUNhdGFsb25pYTESMBAGA1UEBwwJQmFy
Y2Vsb25hMQ4wDAYDVQQKDAVDRUxTQTAeFw0yNDA5MjcwOTM0NTNaFw0zNDA5MjUw
OTM0NTNaMEUxCzAJBgNVBAYTAkVTMRIwEAYDVQQIDAlDYXRhbG9uaWExEjAQBgNV
BAcMCUJhcmNlbG9uYTEOMAwGA1UECgwFQ0VMU0EwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAARs9Byp8GSxR7M/TaRK/aeXYEj4vBQJivJCWmqJtUhuPdTDfc/Eh9SxllrJ
FLZjZzsR79sYQD86I7VU/szqMRuXhoPe4Ff8aJHH78hAEH4DrAGJc4CAupIwu/sX
TVjDNYOjUzBRMB0GA1UdDgQWBBSOlc4xVVkINRchfQvglBkBkBg9FjAfBgNVHSME
GDAWgBSOlc4xVVkINRchfQvglBkBkBg9FjAPBgNVHRMBAf8EBTADAQH/MAoGCCqG
SM49BAMCA2kAMGYCMQCSYRb4DuKIa506ZZIudp9WR3SWc9DbYlJ7IK+Yc2JmRNLn
wnQNXDf4HlrZ0J8Ozy8CMQDs794nwM7Oy+ulmahfovZlUp39HvawxxhbfwqKBgyo
mw3X2RkqK8cGWFf3KlVFjKg=
-----END CERTIFICATE-----

9
server.key Normal file
View File

@ -0,0 +1,9 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQAIg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDBsfq91Ti9egcuNPGkGCK5Jvd4thMc5g7wPf5zCJ1eAyfRhvK3j+M3J
3Ju+XS7Uec2gBwYFK4EEACKhZANiAARs9Byp8GSxR7M/TaRK/aeXYEj4vBQJivJC
WmqJtUhuPdTDfc/Eh9SxllrJFLZjZzsR79sYQD86I7VU/szqMRuXhoPe4Ff8aJHH
78hAEH4DrAGJc4CAupIwu/sXTVjDNYM=
-----END EC PRIVATE KEY-----