commit 2dfbaef6d6e8da66d7c4339ad90832664f4aa15a Author: albert Date: Tue Oct 1 20:28:58 2024 +0200 wip diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/barcode/app/app.go b/barcode/app/app.go new file mode 100644 index 0000000..c18c861 --- /dev/null +++ b/barcode/app/app.go @@ -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 + } + } +} diff --git a/barcode_event.json b/barcode_event.json new file mode 100644 index 0000000..1a40a24 --- /dev/null +++ b/barcode_event.json @@ -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" +} \ No newline at end of file diff --git a/cert.pem b/cert.pem new file mode 100644 index 0000000..f6c274f --- /dev/null +++ b/cert.pem @@ -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----- \ No newline at end of file diff --git a/cmd/barcode.go b/cmd/barcode.go new file mode 100644 index 0000000..70f4d91 --- /dev/null +++ b/cmd/barcode.go @@ -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") +} diff --git a/cmd/bundle.go b/cmd/bundle.go new file mode 100644 index 0000000..633e9b1 --- /dev/null +++ b/cmd/bundle.go @@ -0,0 +1,40 @@ +/* +Copyright © 2024 NAME HERE + +*/ +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") +} diff --git a/cmd/handset.go b/cmd/handset.go new file mode 100644 index 0000000..64a794a --- /dev/null +++ b/cmd/handset.go @@ -0,0 +1,36 @@ +/* +Copyright © 2024 NAME HERE +*/ +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") +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..b5bb6db --- /dev/null +++ b/cmd/root.go @@ -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") +} diff --git a/cmd/sap.go b/cmd/sap.go new file mode 100644 index 0000000..8d56243 --- /dev/null +++ b/cmd/sap.go @@ -0,0 +1,35 @@ +/* +Copyright © 2024 NAME HERE +*/ +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") +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d418527 --- /dev/null +++ b/go.mod @@ -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 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..3ece917 --- /dev/null +++ b/go.sum @@ -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= diff --git a/handset/app/app.go b/handset/app/app.go new file mode 100644 index 0000000..73f5799 --- /dev/null +++ b/handset/app/app.go @@ -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 + } + } +} diff --git a/handset/eventer/eventer.go b/handset/eventer/eventer.go new file mode 100644 index 0000000..dcee8dd --- /dev/null +++ b/handset/eventer/eventer.go @@ -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{}, + } +} diff --git a/handset/handlers/barcode.go b/handset/handlers/barcode.go new file mode 100644 index 0000000..f73be26 --- /dev/null +++ b/handset/handlers/barcode.go @@ -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) + } + } +} diff --git a/handset/handlers/index.go b/handset/handlers/index.go new file mode 100644 index 0000000..b782a45 --- /dev/null +++ b/handset/handlers/index.go @@ -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 + } + } +} diff --git a/handset/routes/routes.go b/handset/routes/routes.go new file mode 100644 index 0000000..a2b8d2b --- /dev/null +++ b/handset/routes/routes.go @@ -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)) +} diff --git a/handset/templates/index.html b/handset/templates/index.html new file mode 100644 index 0000000..03c7b25 --- /dev/null +++ b/handset/templates/index.html @@ -0,0 +1,95 @@ + + + + + + + + + + + Falcon Handset UI + + + + +

Scanner de códigos de barras

+
+
+
+
+ + + + + \ No newline at end of file diff --git a/internal/storage/storage.go b/internal/storage/storage.go new file mode 100644 index 0000000..1ca79ba --- /dev/null +++ b/internal/storage/storage.go @@ -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 +} diff --git a/internal/types/barcode.go b/internal/types/barcode.go new file mode 100644 index 0000000..e1ab087 --- /dev/null +++ b/internal/types/barcode.go @@ -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"` +} diff --git a/internal/types/bundle.go b/internal/types/bundle.go new file mode 100644 index 0000000..7353c48 --- /dev/null +++ b/internal/types/bundle.go @@ -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 +} diff --git a/internal/types/production_order.go b/internal/types/production_order.go new file mode 100644 index 0000000..519d4ee --- /dev/null +++ b/internal/types/production_order.go @@ -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" +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..d495360 --- /dev/null +++ b/main.go @@ -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() +} diff --git a/sap/app/app.go b/sap/app/app.go new file mode 100644 index 0000000..0e899da --- /dev/null +++ b/sap/app/app.go @@ -0,0 +1,5 @@ +package app + +import "github.com/spf13/cobra" + +func Run(cmd *cobra.Command, args []string) {} diff --git a/server.crt b/server.crt new file mode 100644 index 0000000..a6367f9 --- /dev/null +++ b/server.crt @@ -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----- \ No newline at end of file diff --git a/server.key b/server.key new file mode 100644 index 0000000..754cb43 --- /dev/null +++ b/server.key @@ -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----- \ No newline at end of file