{"id":10583,"date":"2021-06-08T10:25:14","date_gmt":"2021-06-08T08:25:14","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=10583"},"modified":"2023-10-25T13:00:03","modified_gmt":"2023-10-25T11:00:03","slug":"dane-przemyslowe-w-internecie-implementacja-rest-api-z-wykorzystaniem-sieci-polowej-modbus","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/dane-przemyslowe-w-internecie-implementacja-rest-api-z-wykorzystaniem-sieci-polowej-modbus\/","title":{"rendered":"Dane przemys\u0142owe w Internecie \u2013 implementacja REST API z wykorzystaniem sieci polowej MODBUS"},"content":{"rendered":"\n<p>Post\u0119puj\u0105ca transformacja cyfrowa dotyka wiele dziedzin \u017cycia oraz gospodarki. Nie omija to r\u00f3wnie\u017c przemys\u0142u poprzez realizacj\u0119 za\u0142o\u017ce\u0144 czwartej rewolucji przemys\u0142owej, opieraj\u0105cej si\u0119 na g\u0142\u0119bokiej integracji system\u00f3w sterowania oraz nadzoru z zaawansowanymi systemami informatycznymi.<\/p>\n\n\n\n<p>Maj\u0105 one za zadanie podnosi\u0107 wska\u017aniki wydajno\u015bci, jako\u015bci oraz bezpiecze\u0144stwa prowadzonych proces\u00f3w produkcyjnych. Pomimo sporych inwestycji przeznaczanych przez przedsi\u0119biorstwa na modernizacj\u0119 aparatury steruj\u0105co-kontrolnej w obiegu nadal funkcjonuj\u0105 urz\u0105dzenia nieprzystosowane do funkcjonowania w aktualnych systemach zarz\u0105dzania obiektem sterowania. W zwi\u0105zku z tym, cz\u0119stym problemem podczas realizacji idei przemys\u0142u 4.0 jest r\u00f3wnie\u017c starzej\u0105ca si\u0119 infrastruktura sieciowa. Istnieje natomiast mo\u017cliwo\u015b\u0107 obni\u017cenia koszt\u00f3w takiej transformacji poprzez wykorzystanie zewn\u0119trznych bibliotek wraz z REST API. W niniejszym przyk\u0142adzie opisana zostanie implementacja REST API z wykorzystaniem sieci polowej MODBUS TCP. W przyk\u0142adzie wykorzystano \u015brodowisko CoDeSys oraz REST API napisane z wykorzystaniem .NET WEB API w j\u0119zyku C#.<\/p>\n\n\n\n<p>MODBUS TCP jest wersj\u0105 otwartego protoko\u0142u MODBUS wykorzystuj\u0105cego ethernet jako medium komunikacyjne zar\u00f3wno przewodowo jak i bezprzewodowo. Wykorzystuje on w komunikacji port 502. Dzia\u0142a on w architekturze klient-serwer (master-slave). W przeciwie\u0144stwie do MODBUS RTU daje to przewag\u0119 w mo\u017cliwo\u015bci zawarcia wielu klient\u00f3w, ani\u017celi jednego w zakresie sieci.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>PLC + MODBUS<\/strong><\/h2>\n\n\n\n<p>Schemat obiektu wygl\u0105da nast\u0119puj\u0105co:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/Modbus-REST-API-Scheme-1.jpg\"><img decoding=\"async\" width=\"1091\" height=\"81\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/Modbus-REST-API-Scheme-1.jpg\" alt=\"schemat obiektu: Soft PLC, Gateway, REST API\" class=\"wp-image-10587\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/Modbus-REST-API-Scheme-1.jpg 1091w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/Modbus-REST-API-Scheme-1-300x22.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/Modbus-REST-API-Scheme-1-1024x76.jpg 1024w\" sizes=\"(max-width: 1091px) 100vw, 1091px\" \/><\/a><\/figure>\n\n\n\n<p>Na wst\u0119pie przygotowujemy struktur\u0119 projektu PLC wraz z przygotowaniem infrastruktury sieciowej dla MODBUS TCP. Device <em>Ethernet<\/em> konfigurujemy zgodnie z aktualn\u0105 dla nas sieci\u0105 Ethernet.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-network-config.jpg\"><img decoding=\"async\" width=\"1092\" height=\"632\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-network-config.jpg\" alt=\"\" class=\"wp-image-10576\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-network-config.jpg 1092w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-network-config-300x174.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-network-config-1024x593.jpg 1024w\" sizes=\"(max-width: 1092px) 100vw, 1092px\" \/><\/a><\/figure>\n\n\n\n<p>Kolejnym krokiem jest przygotowanie mapowania zmiennych sieciowych do wykorzystania&nbsp;w programie.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-Modbus-variables-config.jpg\"><img decoding=\"async\" width=\"1095\" height=\"280\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-Modbus-variables-config.jpg\" alt=\"\" class=\"wp-image-10577\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-Modbus-variables-config.jpg 1095w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-Modbus-variables-config-300x77.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-Modbus-variables-config-1024x262.jpg 1024w\" sizes=\"(max-width: 1095px) 100vw, 1095px\" \/><\/a><\/figure>\n\n\n\n<p>Nale\u017cy koniecznie pami\u0119ta\u0107 o ustawieniu odpowiedniego Taska dla dzia\u0142ania naszej sieci polowej. W przyk\u0142adzie jest to g\u0142\u00f3wny Task wywo\u0142ywany cyklicznie.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-task-set.jpg\"><img decoding=\"async\" width=\"1093\" height=\"114\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-task-set.jpg\" alt=\"\" class=\"wp-image-10578\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-task-set.jpg 1093w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-task-set-300x31.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/CoDeSys-task-set-1024x107.jpg 1024w\" sizes=\"(max-width: 1093px) 100vw, 1093px\" \/><\/a><\/figure>\n\n\n\n<p>Na tym etapie przygotowany projekt PLC jest gotowy do pracy w trybie slave (server), do kt\u00f3rego b\u0119d\u0105 przysy\u0142ane zapytania o dane.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>REST API + NMODBUS<\/strong><\/h2>\n\n\n\n<p>Kolejnym etapem jest przygotowanie REST API w \u015brodowisku .NET. W projekcie wykorzystano bibliotek\u0119 NModbus, kt\u00f3ra pozwala na dost\u0119p do urz\u0105dze\u0144 wspieraj\u0105cych sie\u0107 polow\u0105 MODBUS zar\u00f3wno w wersji RTU jak i TCP. Na wst\u0119pie wymagana jest konfiguracja klienta sieci MODBUS \u2013 w tym przypadku master\u2019a.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic bool Connect()\n{\n   if (_client == null)\n      return false;\n   var retriesTimeSpan = Backoff.LinearBackoff(TimeSpan.FromSeconds(1), 5);\n   var policy = Policy.Handle&lt;SocketException&gt;().WaitAndRetry(retriesTimeSpan);\n   var connectionResult = policy.ExecuteAndCapture(() =&gt; _client.Connect(_hostname, _port));\n   if (connectionResult.Outcome == OutcomeType.Failure)\n   {\n      var validationResult = new TcpClientValidationResult\n      {\n         HasErrors = true,\n         ExceptionType = connectionResult.FinalException.InnerException\n      };\n   validationResult.ErrorMessage = validationResult.GetErrorMessageByExceptionType();\n   ValidationResult = validationResult;\n   }\n   else\n      ValidationResult = new TcpClientValidationResult();\n   return _client.Connected;\n}\n<\/pre><\/div>\n\n\n<p>Ka\u017cdy endpoint wysy\u0142a zapytanie do service\u2019\u00f3w, kt\u00f3re to poprzez Gateway maj\u0105 dost\u0119p do sieci MODBUS.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;HttpGet(&quot;feedMotorSpeed&quot;)]\npublic async Task&lt;IActionResult&gt; GetFeddMotorSpeed()\n{\n   var serviceResponse = await _packagingCellService.GetFeedMotorSpeed();\n   var actionResponse =_actionResponse.GetResponseFromService(serviceResponse);\n   return serviceResponse.ValidationResult.HasErrors ? BadRequest(actionResponse) : Ok(actionResponse);\n}\n<\/pre><\/div>\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic async Task&lt;IServiceResponse&lt;ushort&gt;&gt; GetFeedMotorSpeed()\n{\n    var targetAddresses = _addressProvider.GetAddress(CompressorPackagingCellAddresses.FEED_MOTOR_SPEED);\n    if (HasError(_addressProvider.ValidationResult))\n    {\n        SetResponseError(_addressProvider.ValidationResult);\n        return GetResponse(_packagingCell.Model.FeedMotorSpeed);\n    }\n    _packagingCell.Model.FeedMotorSpeed = await _modbusGateway.Reader.ReadNumberValue(targetAddresses);\n    if (HasError(_modbusGateway.Reader.ValidationResult))\n        SetResponseError(_modbusGateway.Reader.ValidationResult);\n     \n    return GetResponse(_packagingCell.Model.FeedMotorSpeed);\n}\n<\/pre><\/div>\n\n\n<p>Adresy poszczeg\u00f3lnych rejestr\u00f3w sieci MODBUS s\u0105 przechowywane w sta\u0142ych. Walidacja nast\u0119puje przy ka\u017cdym ich wykorzystaniu.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic int GetAddress(string address)\n{\n    var addressModel = _addressParser.Parse(address);\n    var addressValidationResult = _validator.Validate(addressModel);\n    if (!addressValidationResult.HasErrors)\n        _address = addressModel.ByteAddress + addressModel.BitAddress;\n     \n    ValidationResult = addressValidationResult;\n  \n    return _address;\n}\n<\/pre><\/div>\n\n\n<p>Biblioteka Polly zajmuje si\u0119 realizacj\u0105 podejmowania pr\u00f3b ponownego po\u0142\u0105czenia oraz ponownego odczytu danych z sieci polowej. Dzi\u0119ki niej \u0142atwo mo\u017cna skonfigurowa\u0107 polityk\u0119 obs\u0142ugi wyj\u0105tk\u00f3w oraz podejmowania ponownych pr\u00f3b wykonania akcji.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic async Task&lt;ushort&gt; ReadNumberValue(int address)\n{\n    var response =  0;\n    using (var client = _client.GetClient())\n    {\n        var timeSpan = Backoff.LinearBackoff(TimeSpan.FromSeconds(1), 4);\n        var modbusMasterPolicy = Policy.Handle&lt;Exception&gt;().WaitAndRetry(timeSpan);\n        var policyExecutionResult = modbusMasterPolicy.ExecuteAndCapture(() =&gt; SetModbusMaster(client));\n        if(policyExecutionResult.Outcome == OutcomeType.Failure)\n        {\n            var validationResult = new ModbusReadingValidationResult();\n            validationResult.GetFromSlaveException(policyExecutionResult.FinalException, (int)EModbusTransportErrorCode.ConnectionError);\n            ValidationResult = validationResult;\n            return (ushort)response;\n        }\n        var modbusReadingPolicy = Policy.Handle&lt;Exception&gt;().WaitAndRetryAsync(timeSpan);\n        var modbusReadingPolicyResult =  modbusReadingPolicy.ExecuteAndCaptureAsync(async () =&gt;\n            await _modbusMaster.ReadInputRegistersAsync(0, (ushort)address, 1).ConfigureAwait(false));\n        if(modbusReadingPolicyResult.Result.Outcome == OutcomeType.Failure)\n        {\n            var validationResult = new ModbusReadingValidationResult();\n            validationResult.GetFromSlaveException(modbusReadingPolicyResult.Result.FinalException,\n                            (int)EModbusTransportErrorCode.ReadingError);\n            ValidationResult = validationResult;\n            return (ushort)response;\n        }\n        response = modbusReadingPolicyResult.Result.Result&#x5B;0];\n    }\n    return (ushort)response;\n}\n<\/pre><\/div>\n\n\n<p>Nast\u0119pnie przechwycona odpowied\u017a lub b\u0142\u0105d wynikaj\u0105cy z niepowodzenia operacji przekazywane s\u0105 do metody formatuj\u0105cej odpowied\u017a ko\u0144cow\u0105.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npublic ServiceResponseBase GetResponseFromService&amp;lt;T&gt;(IServiceResponse&amp;lt;T&gt; serviceResponse)\n{\n    var responseModel = new ModbusActionResponseModel\n    {\n        ResponseMessage = serviceResponse.ValidationResult.HasErrors ? \n            SetErrorMessage(serviceResponse.ValidationResult) : \n            SetPayloadMessage(serviceResponse.Payload),\n    };\n    responseModel.ResponseMessage.ResponseIssued = DateTime.Now;\n    return responseModel.ResponseMessage;\n}\n<\/pre><\/div>\n\n\n<p>Te same kroki odpowiadaj\u0105 r\u00f3wnie\u017c ustawianiu rejestr\u00f3w MODBUS. W tym celu nale\u017cy wykorzysta\u0107 inne (poda\u0107 jakie) metody przygotowane w ramach biblioteki NModbus. Metoda \u201eWriteSingleRegister\u201d wpisuje warto\u015b\u0107 do ca\u0142ego rejestru \u2013 jest ni\u0105 najcz\u0119\u015bciej warto\u015b\u0107 liczbowa. Natomiast metoda \u201eWriteSingleCoil\u201d pozwala na zmian\u0119 stanu pojedynczego bitu w rejestrze.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nvoid WriteSingleRegister(byte slaveAddress, ushort registerAddress, ushort value);\nvoid WriteSingleCoil(byte slaveAddress, ushort coilAddress, bool value);\n<\/pre><\/div>\n\n\n<p>Jak wida\u0107, niew\u0105tpliw\u0105 zalet\u0105 takiego rozwi\u0105zania jest jego niski koszt implementacji. O ile sama sie\u0107 MODBUS nie jest przystosowana do transmisji du\u017cych pakiet\u00f3w danych (253 bajty), o tyle przy wymianie niewielkich ilo\u015bci informacji jest w stanie zaspokoi\u0107 potrzeby monitorowania podstawowych lub wra\u017cliwych danych o obiekcie. Otwiera to drog\u0119 do archiwizowania i wizualizowania danych z obiektu oraz mo\u017cliwo\u015b\u0107 zadawania sygna\u0142\u00f3w steruj\u0105cych zdalnie. Mo\u017cliwo\u015bci opisanej wy\u017cej konfiguracji mog\u0105 r\u00f3wnie\u017c s\u0142u\u017cy\u0107 do prototypowania r\u00f3\u017cnych rozwi\u0105za\u0144 przemys\u0142owych \u2013 od niewielkich instalacji sterowania i nadzoru do system\u00f3w archiwizacji oraz agregacji i prezentacji danych w systemach informatycznych.&nbsp; Istotnym elementem jest r\u00f3wnie\u017c zabezpieczanie takiej instalacji przed niepo\u017c\u0105danym dost\u0119pem. W takim przypadku mo\u017ce on nie tylko narazi\u0107 obiekt na utrat\u0119 danych, ale r\u00f3wnie\u017c doprowadzi\u0107 obiekt do stanu niebezpiecznego.<\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;10583&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;1&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( vote: 1)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Dane przemys\u0142owe w Internecie \u2013 implementacja REST API z wykorzystaniem sieci polowej MODBUS&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( vote: 1)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Post\u0119puj\u0105ca transformacja cyfrowa dotyka wiele dziedzin \u017cycia oraz gospodarki. Nie omija to r\u00f3wnie\u017c przemys\u0142u poprzez realizacj\u0119 za\u0142o\u017ce\u0144 czwartej rewolucji przemys\u0142owej, &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/dane-przemyslowe-w-internecie-implementacja-rest-api-z-wykorzystaniem-sieci-polowej-modbus\/\">Continued<\/a><\/p>\n","protected":false},"author":280,"featured_media":10668,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[129,1040,956],"class_list":["post-10583","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-c","tag-plc","tag-rest-api"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2021\/05\/Modbus.png","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/10583"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/280"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=10583"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/10583\/revisions"}],"predecessor-version":[{"id":25229,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/10583\/revisions\/25229"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/10668"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=10583"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=10583"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=10583"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}